xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision b94d7ded0a05f1bbd5e48daa6f92b28259c75b44)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
25e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h>
35e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.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;
269566063dSJacob Faibussowitsch   PetscCall(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));
329566063dSJacob Faibussowitsch     PetscCall(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) {
399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&sing));
40a13144ffSStefano Zampini   } else {
41a13144ffSStefano Zampini     sing = rwork;
42a13144ffSStefano Zampini   }
43a13144ffSStefano Zampini 
44a13144ffSStefano Zampini   /* SVD */
459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nr*nr,&U));
469566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(nr,&bM));
479566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(nc,&bN));
489566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(ulw,&lwork));
499566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A,&data));
509566063dSJacob Faibussowitsch   PetscCall(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
549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(5*n,&rwork2));
55abee2b68SSebastian Grimberg   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,rwork2,&lierr));
569566063dSJacob Faibussowitsch   PetscCall(PetscFree(rwork2));
57abee2b68SSebastian Grimberg #endif
589566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
5928b400f6SJacob Faibussowitsch   PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
609566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A,&data));
61a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
62a13144ffSStefano Zampini   if (!rwork) {
639566063dSJacob Faibussowitsch     PetscCall(PetscFree(sing));
64a13144ffSStefano Zampini   }
65a13144ffSStefano Zampini   if (!work) {
669566063dSJacob Faibussowitsch     PetscCall(PetscFree(uwork));
67a13144ffSStefano Zampini   }
68a13144ffSStefano Zampini   /* create B */
69f498cd09SStefano Zampini   if (!range) {
709566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B));
719566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(*B,&data));
729566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data,U+nr*i,(nr-i)*nr));
73f498cd09SStefano Zampini   } else {
749566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B));
759566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(*B,&data));
769566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data,U,i*nr));
77f498cd09SStefano Zampini   }
789566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(*B,&data));
799566063dSJacob Faibussowitsch   PetscCall(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;
969566063dSJacob Faibussowitsch   PetscCall(ISGetSize(edge,&esize));
97c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
989566063dSJacob Faibussowitsch   PetscCall(ISGetSize(extrow,&rsize));
999566063dSJacob Faibussowitsch   PetscCall(ISGetSize(extcol,&csize));
100a13144ffSStefano Zampini 
101a13144ffSStefano Zampini   /* gradients */
102a13144ffSStefano Zampini   ptr  = work + 5*esize;
1039566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE));
1049566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins));
1059566063dSJacob Faibussowitsch   PetscCall(MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins));
1069566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&GE));
107a13144ffSStefano Zampini 
108a13144ffSStefano Zampini   /* constants */
109a13144ffSStefano Zampini   ptr += rsize*csize;
1109566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd));
1119566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE));
1129566063dSJacob Faibussowitsch   PetscCall(MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd));
1139566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&GE));
1149566063dSJacob Faibussowitsch   PetscCall(MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins));
1159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&GEd));
1161e0482f5SStefano Zampini 
1171e0482f5SStefano Zampini   if (corners) {
1181e0482f5SStefano Zampini     Mat               GEc;
1191683a169SBarry Smith     const PetscScalar *vals;
1201683a169SBarry Smith     PetscScalar       v;
1211e0482f5SStefano Zampini 
1229566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc));
1239566063dSJacob Faibussowitsch     PetscCall(MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd));
1249566063dSJacob Faibussowitsch     PetscCall(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;
1299566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(GEd,&vals));
1309566063dSJacob Faibussowitsch     PetscCall(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++);
1369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer));
1379566063dSJacob Faibussowitsch       PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB));
1389566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)GEc,"GEc"));
1399566063dSJacob Faibussowitsch       PetscCall(MatView(GEc,viewer));
1409566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)(*GKins),"GK"));
1419566063dSJacob Faibussowitsch       PetscCall(MatView(*GKins,viewer));
1429566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)GEd,"Gproj"));
1439566063dSJacob Faibussowitsch       PetscCall(MatView(GEd,viewer));
1449566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&viewer));
1451e0482f5SStefano Zampini     }
1461e0482f5SStefano Zampini #endif
1479566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&GEd));
1489566063dSJacob Faibussowitsch     PetscCall(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 
179a13144ffSStefano Zampini   PetscFunctionBegin;
180213b8bfaSStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
181213b8bfaSStefano Zampini      it assumes G is given in global ordering for all the dofs.
182213b8bfaSStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
183213b8bfaSStefano Zampini   order      = pcbddc->nedorder;
184213b8bfaSStefano Zampini   conforming = pcbddc->conforming;
185213b8bfaSStefano Zampini   field      = pcbddc->nedfield;
186213b8bfaSStefano Zampini   global     = pcbddc->nedglobal;
187213b8bfaSStefano Zampini   setprimal  = PETSC_FALSE;
188a13144ffSStefano Zampini   print      = PETSC_FALSE;
189213b8bfaSStefano Zampini   singular   = PETSC_FALSE;
190a13144ffSStefano Zampini 
191213b8bfaSStefano Zampini   /* Command line customization */
192d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");
1939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL));
1949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL));
1959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL));
196213b8bfaSStefano Zampini   /* print debug info TODO: to be removed */
1979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL));
198d0609cedSBarry Smith   PetscOptionsEnd();
199213b8bfaSStefano Zampini 
200213b8bfaSStefano Zampini   /* Return if there are no edges in the decomposition and the problem is not singular */
2019566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalToGlobalMapping(pc->pmat,&al2g,NULL));
2029566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(al2g,&n));
2039566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
204213b8bfaSStefano Zampini   if (!singular) {
2059566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(matis->counter,(const PetscScalar**)&vals));
206a13144ffSStefano Zampini     lrc[0] = PETSC_FALSE;
207c2151214SStefano Zampini     for (i=0;i<n;i++) {
208a13144ffSStefano Zampini       if (PetscRealPart(vals[i]) > 2.) {
209a13144ffSStefano Zampini         lrc[0] = PETSC_TRUE;
210a13144ffSStefano Zampini         break;
211a13144ffSStefano Zampini       }
212a13144ffSStefano Zampini     }
2139566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals));
2141c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm));
215a13144ffSStefano Zampini     if (!lrc[1]) PetscFunctionReturn(0);
216213b8bfaSStefano Zampini   }
217a13144ffSStefano Zampini 
218213b8bfaSStefano Zampini   /* Get Nedelec field */
21963a3b9bcSJacob Faibussowitsch   PetscCheck(!pcbddc->n_ISForDofsLocal || field < pcbddc->n_ISForDofsLocal,comm,PETSC_ERR_USER,"Invalid field for Nedelec %" PetscInt_FMT ": number of fields is %" PetscInt_FMT,field,pcbddc->n_ISForDofsLocal);
220213b8bfaSStefano Zampini   if (pcbddc->n_ISForDofsLocal && field >= 0) {
2219566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]));
222c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
2239566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(nedfieldlocal,&ne));
224213b8bfaSStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) {
225213b8bfaSStefano Zampini     ne            = n;
226213b8bfaSStefano Zampini     nedfieldlocal = NULL;
227213b8bfaSStefano Zampini     global        = PETSC_TRUE;
228213b8bfaSStefano Zampini   } else if (field == PETSC_DECIDE) {
229213b8bfaSStefano Zampini     PetscInt rst,ren,*idx;
230213b8bfaSStefano Zampini 
2319566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(matis->sf_leafdata,n));
2329566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n));
2339566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren));
234213b8bfaSStefano Zampini     for (i=rst;i<ren;i++) {
235213b8bfaSStefano Zampini       PetscInt nc;
236213b8bfaSStefano Zampini 
2379566063dSJacob Faibussowitsch       PetscCall(MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL));
238213b8bfaSStefano Zampini       if (nc > 1) matis->sf_rootdata[i-rst] = 1;
2399566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL));
240213b8bfaSStefano Zampini     }
2419566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
2429566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
2439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&idx));
244213b8bfaSStefano Zampini     for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i;
2459566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal));
246213b8bfaSStefano Zampini   } else {
247213b8bfaSStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
248213b8bfaSStefano Zampini   }
249213b8bfaSStefano Zampini 
250213b8bfaSStefano Zampini   /* Sanity checks */
2517827d75bSBarry Smith   PetscCheck(order || conforming,comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
25228b400f6SJacob Faibussowitsch   PetscCheck(!pcbddc->user_ChangeOfBasisMatrix,comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
25363a3b9bcSJacob Faibussowitsch   PetscCheck(!order || (ne%order == 0),PETSC_COMM_SELF,PETSC_ERR_USER,"The number of local edge dofs %" PetscInt_FMT " is not a multiple of the order %" PetscInt_FMT,ne,order);
254213b8bfaSStefano Zampini 
255213b8bfaSStefano Zampini   /* Just set primal dofs and return */
2561e0482f5SStefano Zampini   if (setprimal) {
257eee23b56SStefano Zampini     IS       enedfieldlocal;
258eee23b56SStefano Zampini     PetscInt *eidxs;
259eee23b56SStefano Zampini 
2609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ne,&eidxs));
2619566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(matis->counter,(const PetscScalar**)&vals));
262213b8bfaSStefano Zampini     if (nedfieldlocal) {
2639566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(nedfieldlocal,&idxs));
264eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
265eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
266eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
267eee23b56SStefano Zampini         }
268eee23b56SStefano Zampini       }
2699566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(nedfieldlocal,&idxs));
270213b8bfaSStefano Zampini     } else {
271213b8bfaSStefano Zampini       for (i=0,cum=0;i<ne;i++) {
272213b8bfaSStefano Zampini         if (PetscRealPart(vals[i]) > 2.) {
273213b8bfaSStefano Zampini           eidxs[cum++] = i;
274213b8bfaSStefano Zampini         }
275213b8bfaSStefano Zampini       }
276213b8bfaSStefano Zampini     }
2779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals));
2789566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal));
2799566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal));
2809566063dSJacob Faibussowitsch     PetscCall(PetscFree(eidxs));
2819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&nedfieldlocal));
2829566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&enedfieldlocal));
2831e0482f5SStefano Zampini     PetscFunctionReturn(0);
2841e0482f5SStefano Zampini   }
285a13144ffSStefano Zampini 
286213b8bfaSStefano Zampini   /* Compute some l2g maps */
287213b8bfaSStefano Zampini   if (nedfieldlocal) {
288c2151214SStefano Zampini     IS is;
289c2151214SStefano Zampini 
290c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
2919566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g));
2921e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2939566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is));
2949566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&al2g));
2951e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
2961e0482f5SStefano Zampini     if (global) {
2979566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)al2g));
2981e0482f5SStefano Zampini       el2g = al2g;
2991e0482f5SStefano Zampini     } else {
3001e0482f5SStefano Zampini       IS gis;
3011e0482f5SStefano Zampini 
3029566063dSJacob Faibussowitsch       PetscCall(ISRenumber(is,NULL,NULL,&gis));
3039566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(gis,&el2g));
3049566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&gis));
3051e0482f5SStefano Zampini     }
3069566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
307c2151214SStefano Zampini   } else {
3081e0482f5SStefano Zampini     /* restore default */
3091e0482f5SStefano Zampini     pcbddc->nedfield = -1;
3101e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
3119566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)al2g));
3129566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)al2g));
3131e0482f5SStefano Zampini     el2g = al2g;
314c2151214SStefano Zampini     fl2g = NULL;
315c2151214SStefano Zampini   }
316a13144ffSStefano Zampini 
317213b8bfaSStefano Zampini   /* Start communication to drop connections for interior edges (for cc analysis only) */
3189566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_leafdata,n));
3199566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n));
320c2151214SStefano Zampini   if (nedfieldlocal) {
3219566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(nedfieldlocal,&idxs));
322c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
3239566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(nedfieldlocal,&idxs));
324c2151214SStefano Zampini   } else {
325c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
326c2151214SStefano Zampini   }
3279566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM));
3289566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM));
329213b8bfaSStefano Zampini 
330213b8bfaSStefano Zampini   if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */
3319566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G));
3329566063dSJacob Faibussowitsch     PetscCall(MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE));
3331e0482f5SStefano Zampini     if (global) {
3341e0482f5SStefano Zampini       PetscInt rst;
3351e0482f5SStefano Zampini 
3369566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(G,&rst,NULL));
337c2151214SStefano Zampini       for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
338c2151214SStefano Zampini         if (matis->sf_rootdata[i] < 2) {
339c2151214SStefano Zampini           matis->sf_rootdata[cum++] = i + rst;
340c2151214SStefano Zampini         }
341c2151214SStefano Zampini       }
3429566063dSJacob Faibussowitsch       PetscCall(MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE));
3439566063dSJacob Faibussowitsch       PetscCall(MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL));
3441e0482f5SStefano Zampini     } else {
3451e0482f5SStefano Zampini       PetscInt *tbz;
3461e0482f5SStefano Zampini 
3479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(ne,&tbz));
3489566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
3499566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
3509566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(nedfieldlocal,&idxs));
3511e0482f5SStefano Zampini       for (i=0,cum=0;i<ne;i++)
3521e0482f5SStefano Zampini         if (matis->sf_leafdata[idxs[i]] == 1)
3531e0482f5SStefano Zampini           tbz[cum++] = i;
3549566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(nedfieldlocal,&idxs));
3559566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz));
3569566063dSJacob Faibussowitsch       PetscCall(MatZeroRows(G,cum,tbz,0.,NULL,NULL));
3579566063dSJacob Faibussowitsch       PetscCall(PetscFree(tbz));
3581e0482f5SStefano Zampini     }
359213b8bfaSStefano Zampini   } else { /* we need the entire G to infer the nullspace */
3609566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->discretegradient));
361213b8bfaSStefano Zampini     G    = pcbddc->discretegradient;
362213b8bfaSStefano Zampini   }
363a13144ffSStefano Zampini 
364a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
3659566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(el2g,&idxs));
3669566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned));
3679566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall));
3689566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(el2g,&idxs));
3699566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&lned));
3709566063dSJacob Faibussowitsch   PetscCall(MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis));
3719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lGall));
3729566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(lGis,&lG));
373a13144ffSStefano Zampini 
374213b8bfaSStefano Zampini   /* SF for nodal dofs communications */
3759566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(G,NULL,&Lv));
3769566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalToGlobalMapping(lGis,NULL,&vl2g));
3779566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)vl2g));
3789566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(vl2g,&nv));
3799566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm,&sfv));
3809566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(vl2g,&idxs));
3819566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs));
3829566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs));
383213b8bfaSStefano Zampini   i    = singular ? 2 : 1;
3849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots));
385a13144ffSStefano Zampini 
3861e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
3879566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)lG));
3889566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lGis));
3899566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&G));
390a13144ffSStefano Zampini 
391213b8bfaSStefano Zampini   if (print) {
3929566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)lG,"initial_lG"));
3939566063dSJacob Faibussowitsch     PetscCall(MatView(lG,NULL));
394213b8bfaSStefano Zampini   }
395213b8bfaSStefano Zampini 
396213b8bfaSStefano Zampini   /* Save lG for values insertion in change of basis */
3979566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(lG,MAT_COPY_VALUES,&lGinit));
3980569b399SStefano Zampini 
399a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
4009566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(lG,MAT_COPY_VALUES,&lGe));
4019566063dSJacob Faibussowitsch   PetscCall(MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE));
4029566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nv,&btv));
4039566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(ne,&bte));
4049566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(ne,&btb));
4059566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(ne,&btbd));
4069566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nv,&btvcand));
407a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
408a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
409a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
410c2151214SStefano Zampini     IS is;
411c2151214SStefano Zampini 
412c2151214SStefano Zampini     if (fl2g) {
4139566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is));
414c2151214SStefano Zampini     } else {
415c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
416c2151214SStefano Zampini     }
4179566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is,&cum));
4189566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,&idxs));
419a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
420a13144ffSStefano Zampini       if (idxs[i] >= 0) {
4219566063dSJacob Faibussowitsch         PetscCall(PetscBTSet(btb,idxs[i]));
4229566063dSJacob Faibussowitsch         PetscCall(PetscBTSet(btbd,idxs[i]));
423a13144ffSStefano Zampini       }
424a13144ffSStefano Zampini     }
4259566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is,&idxs));
426c2151214SStefano Zampini     if (fl2g) {
4279566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
428c2151214SStefano Zampini     }
429a13144ffSStefano Zampini   }
430a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
431c2151214SStefano Zampini     IS is;
432c2151214SStefano Zampini 
433c2151214SStefano Zampini     if (fl2g) {
4349566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is));
435c2151214SStefano Zampini     } else {
436c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
437c2151214SStefano Zampini     }
4389566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is,&cum));
4399566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,&idxs));
440a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
441a13144ffSStefano Zampini       if (idxs[i] >= 0) {
4429566063dSJacob Faibussowitsch         PetscCall(PetscBTSet(btb,idxs[i]));
443a13144ffSStefano Zampini       }
444a13144ffSStefano Zampini     }
4459566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is,&idxs));
446c2151214SStefano Zampini     if (fl2g) {
4479566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
448a13144ffSStefano Zampini     }
449c2151214SStefano Zampini   }
450c2151214SStefano Zampini 
451213b8bfaSStefano Zampini   /* Count neighs per dof */
4529566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetNodeInfo(el2g,NULL,&ecount,&eneighs));
4539566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetNodeInfo(vl2g,NULL,&vcount,&vneighs));
454637e8532SStefano Zampini 
4557d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
4567d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
4579566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(ne,&btee));
45862b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
459b63b1311SStefano Zampini     if ((ecount[i] > 2 && !PetscBTLookup(btbd,i)) || (ecount[i] == 2 && PetscBTLookup(btb,i))) {
4609566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(btee,i));
46162b0c6f7SStefano Zampini     }
46262b0c6f7SStefano Zampini   }
4639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ne,&marks));
46462b0c6f7SStefano Zampini   if (!conforming) {
4659566063dSJacob Faibussowitsch     PetscCall(MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt));
4669566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
46762b0c6f7SStefano Zampini   }
4689566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
4699566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(lGe,&vals));
47062b0c6f7SStefano Zampini   cum  = 0;
471a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
472dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
47362b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
474a13144ffSStefano Zampini       marks[cum++] = i;
475dec27d64SStefano Zampini       continue;
476dec27d64SStefano Zampini     }
477dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
47862b0c6f7SStefano Zampini     if (!conforming) {
47962b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
480a13144ffSStefano Zampini         marks[cum++] = i;
4819566063dSJacob Faibussowitsch         PetscCall(PetscBTSet(bte,i));
482a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
4839566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(btv,jj[j]));
484a13144ffSStefano Zampini         }
48562b0c6f7SStefano Zampini       } else {
48662b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
48762b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
48862b0c6f7SStefano Zampini            - at most 2 endpoints
48962b0c6f7SStefano Zampini            - order-1 interior nodal dofs
49062b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
49162b0c6f7SStefano Zampini         */
49262b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
49362b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
49462b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
49562b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
49662b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
49762b0c6f7SStefano Zampini           if (nconn > order) ends++;
49862b0c6f7SStefano Zampini           else if (nconn == order) ints++;
49962b0c6f7SStefano Zampini           else undef++;
50062b0c6f7SStefano Zampini         }
50162b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
50262b0c6f7SStefano Zampini           marks[cum++] = i;
5039566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(bte,i));
50462b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
5059566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(btv,jj[j]));
50662b0c6f7SStefano Zampini           }
50762b0c6f7SStefano Zampini         }
50862b0c6f7SStefano Zampini       }
509a13144ffSStefano Zampini     }
510dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
511dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
512dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
513dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
514a13144ffSStefano Zampini     }
515dec27d64SStefano Zampini   }
5169566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btee));
5179566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(lGe,&vals));
5189566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
51962b0c6f7SStefano Zampini   if (!conforming) {
5209566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
5219566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lGt));
52262b0c6f7SStefano Zampini   }
5239566063dSJacob Faibussowitsch   PetscCall(MatZeroRows(lGe,cum,marks,0.,NULL,NULL));
524637e8532SStefano Zampini 
525b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5269566063dSJacob Faibussowitsch   PetscCall(MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt));
527a13144ffSStefano Zampini   if (print) {
5289566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)lGe,"edgerestr_lG"));
5299566063dSJacob Faibussowitsch     PetscCall(MatView(lGe,NULL));
5309566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt"));
5319566063dSJacob Faibussowitsch     PetscCall(MatView(lGt,NULL));
532a13144ffSStefano Zampini   }
5339566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
5349566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(lGt,&vals));
535a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
536637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5377d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
538b03ebc13SStefano Zampini     if (!order) { /* variable order */
539dec27d64SStefano Zampini       PetscReal vorder = 0.;
540dec27d64SStefano Zampini 
541dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
542dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
54363a3b9bcSJacob Faibussowitsch       PetscCheck(vorder-test <= PETSC_SQRT_MACHINE_EPSILON,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%" PetscInt_FMT ")",(double)vorder,test);
544dec27d64SStefano Zampini       ord  = 1;
545dec27d64SStefano Zampini     }
5466bdcaf15SBarry 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);
547637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
5487d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
5497d871cd7SStefano Zampini         bdir = PETSC_TRUE;
5507d871cd7SStefano Zampini         break;
5517d871cd7SStefano Zampini       }
552637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
553637e8532SStefano Zampini         sneighs = PETSC_FALSE;
554637e8532SStefano Zampini       } else {
555637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
556637e8532SStefano Zampini         for (k=0;k<vc;k++) {
557637e8532SStefano Zampini           if (vn[k] != en[k]) {
558637e8532SStefano Zampini             sneighs = PETSC_FALSE;
559637e8532SStefano Zampini             break;
560637e8532SStefano Zampini           }
561637e8532SStefano Zampini         }
562637e8532SStefano Zampini       }
563637e8532SStefano Zampini     }
5647d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
56563a3b9bcSJacob Faibussowitsch       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %" PetscInt_FMT " (%s %s %s)\n",i,PetscBools[!sneighs],PetscBools[test >= 3*ord],PetscBools[bdir]);
5669566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(btv,i));
567dec27d64SStefano Zampini     } else if (test == ord) {
568b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
56963a3b9bcSJacob Faibussowitsch         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %" PetscInt_FMT "\n",i);
5709566063dSJacob Faibussowitsch         PetscCall(PetscBTSet(btv,i));
571a13144ffSStefano Zampini       } else {
57263a3b9bcSJacob Faibussowitsch         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %" PetscInt_FMT "\n",i);
5739566063dSJacob Faibussowitsch         PetscCall(PetscBTSet(btvcand,i));
574a13144ffSStefano Zampini       }
575a13144ffSStefano Zampini     }
576a13144ffSStefano Zampini   }
5779566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(el2g,NULL,&ecount,&eneighs));
5789566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(vl2g,NULL,&vcount,&vneighs));
5799566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btbd));
580b03ebc13SStefano Zampini 
581b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
582b03ebc13SStefano Zampini   if (order != 1) {
583b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
5849566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
585b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
586b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
587b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
588b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
589b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
590b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
591b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
592b03ebc13SStefano Zampini             PetscInt v = jjt[k];
593b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
594b03ebc13SStefano Zampini               found = PETSC_TRUE;
595b03ebc13SStefano Zampini               break;
596b03ebc13SStefano Zampini             }
597b03ebc13SStefano Zampini           }
598b03ebc13SStefano Zampini         }
599b03ebc13SStefano Zampini         if (!found) {
60063a3b9bcSJacob Faibussowitsch           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %" PetscInt_FMT " CLEARED\n",i);
6019566063dSJacob Faibussowitsch           PetscCall(PetscBTClear(btvcand,i));
602b03ebc13SStefano Zampini         } else {
60363a3b9bcSJacob Faibussowitsch           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %" PetscInt_FMT " ACCEPTED\n",i);
604b03ebc13SStefano Zampini         }
605b03ebc13SStefano Zampini       }
606b03ebc13SStefano Zampini     }
6079566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
608b03ebc13SStefano Zampini   }
6099566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(lGt,&vals));
6109566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
6119566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lGe));
612a13144ffSStefano Zampini 
613a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6149566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lGt));
6159566063dSJacob Faibussowitsch   PetscCall(MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt));
6169566063dSJacob Faibussowitsch   PetscCall(MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE));
617a13144ffSStefano Zampini 
6184e64d54eSstefano_zampini   /* Mark interior nodal dofs */
6199566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared));
6209566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nv,&btvi));
621a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
622a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6239566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(btvi,shared[i][j]));
624a13144ffSStefano Zampini     }
625a13144ffSStefano Zampini   }
6269566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared));
627a13144ffSStefano Zampini 
628a13144ffSStefano Zampini   /* communicate corners and splitpoints */
6299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nv,&vmarks));
6309566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(sfvleaves,nv));
6319566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(sfvroots,Lv));
632a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
633a13144ffSStefano Zampini 
634a13144ffSStefano Zampini   if (print) {
635a13144ffSStefano Zampini     IS tbz;
636a13144ffSStefano Zampini 
637a13144ffSStefano Zampini     cum = 0;
638a13144ffSStefano Zampini     for (i=0;i<nv;i++)
639a13144ffSStefano Zampini       if (sfvleaves[i])
640a13144ffSStefano Zampini         vmarks[cum++] = i;
641a13144ffSStefano Zampini 
6429566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz));
6439566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local"));
6449566063dSJacob Faibussowitsch     PetscCall(ISView(tbz,NULL));
6459566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&tbz));
646a13144ffSStefano Zampini   }
647a13144ffSStefano Zampini 
6489566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM));
6499566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM));
6509566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves,MPI_REPLACE));
6519566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves,MPI_REPLACE));
652a13144ffSStefano Zampini 
6534e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
6544e64d54eSstefano_zampini      and interior nodal dofs */
655a13144ffSStefano Zampini   cum = 0;
656a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
657a13144ffSStefano Zampini     if (sfvleaves[i]) {
658a13144ffSStefano Zampini       vmarks[cum++] = i;
6599566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(btv,i));
660a13144ffSStefano Zampini     }
6614e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
662a13144ffSStefano Zampini   }
6639566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btvi));
664a13144ffSStefano Zampini   if (print) {
665a13144ffSStefano Zampini     IS tbz;
666a13144ffSStefano Zampini 
6679566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz));
6689566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior"));
6699566063dSJacob Faibussowitsch     PetscCall(ISView(tbz,NULL));
6709566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&tbz));
671a13144ffSStefano Zampini   }
6729566063dSJacob Faibussowitsch   PetscCall(MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL));
6739566063dSJacob Faibussowitsch   PetscCall(PetscFree(vmarks));
6749566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfv));
6759566063dSJacob Faibussowitsch   PetscCall(PetscFree2(sfvleaves,sfvroots));
676a13144ffSStefano Zampini 
677a13144ffSStefano Zampini   /* Recompute G */
6789566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lG));
6799566063dSJacob Faibussowitsch   PetscCall(MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG));
680a13144ffSStefano Zampini   if (print) {
6819566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)lG,"used_lG"));
6829566063dSJacob Faibussowitsch     PetscCall(MatView(lG,NULL));
6839566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)lGt,"used_lGt"));
6849566063dSJacob Faibussowitsch     PetscCall(MatView(lGt,NULL));
685a13144ffSStefano Zampini   }
686a13144ffSStefano Zampini 
687a13144ffSStefano Zampini   /* Get primal dofs (if any) */
688a13144ffSStefano Zampini   cum = 0;
689a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
690a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
691a13144ffSStefano Zampini   }
6921baa6e33SBarry Smith   if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g,cum,marks,marks));
6939566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals));
694a13144ffSStefano Zampini   if (print) {
6959566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs"));
6969566063dSJacob Faibussowitsch     PetscCall(ISView(primals,NULL));
697a13144ffSStefano Zampini   }
6989566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&bte));
699c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
7009566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc,primals));
7019566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&primals));
702a13144ffSStefano Zampini 
703a13144ffSStefano Zampini   /* Compute edge connectivity */
7049566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_"));
7054222ddf1SHong Zhang 
7064222ddf1SHong Zhang   /* Symbolic conn = lG*lGt */
7079566063dSJacob Faibussowitsch   PetscCall(MatProductCreate(lG,lGt,NULL,&conn));
7089566063dSJacob Faibussowitsch   PetscCall(MatProductSetType(conn,MATPRODUCT_AB));
7099566063dSJacob Faibussowitsch   PetscCall(MatProductSetAlgorithm(conn,"default"));
7109566063dSJacob Faibussowitsch   PetscCall(MatProductSetFill(conn,PETSC_DEFAULT));
7119566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)conn,"econn_"));
7129566063dSJacob Faibussowitsch   PetscCall(MatProductSetFromOptions(conn));
7139566063dSJacob Faibussowitsch   PetscCall(MatProductSymbolic(conn));
7144222ddf1SHong Zhang 
7159566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
716c2151214SStefano Zampini   if (fl2g) {
717c2151214SStefano Zampini     PetscBT   btf;
718c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
719c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
720c2151214SStefano Zampini 
721c2151214SStefano Zampini     /* create CSR for all local dofs */
7229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n+1,&iia));
723c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
72463a3b9bcSJacob Faibussowitsch       PetscCheck(pcbddc->mat_graph->nvtxs_csr == n,PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid size of CSR graph %" PetscInt_FMT ". Should be %" PetscInt_FMT,pcbddc->mat_graph->nvtxs_csr,n);
725c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
726c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
727c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
728c2151214SStefano Zampini       rest = PETSC_TRUE;
7299566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done));
730c2151214SStefano Zampini     } else {
731c2151214SStefano Zampini       free   = PETSC_TRUE;
7329566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(n+1,&iiu,n,&jju));
733c2151214SStefano Zampini       iiu[0] = 0;
734c2151214SStefano Zampini       for (i=0;i<n;i++) {
735c2151214SStefano Zampini         iiu[i+1] = i+1;
736c2151214SStefano Zampini         jju[i]   = -1;
737d904f53bSStefano Zampini       }
738c2151214SStefano Zampini     }
739c2151214SStefano Zampini 
740c2151214SStefano Zampini     /* import sizes of CSR */
741c2151214SStefano Zampini     iia[0] = 0;
742c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
743c2151214SStefano Zampini 
744c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
7459566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(n,&btf));
7469566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(nedfieldlocal,&idxs));
747c2151214SStefano Zampini     for (i=0;i<ne;i++) {
7489566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(btf,idxs[i]));
749c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
750c2151214SStefano Zampini     }
751c2151214SStefano Zampini 
752c2151214SStefano Zampini     /* iia in CSR */
753c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
754c2151214SStefano Zampini 
755c2151214SStefano Zampini     /* jja in CSR */
7569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(iia[n],&jja));
757c2151214SStefano Zampini     for (i=0;i<n;i++)
758c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
759c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
760c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
761c2151214SStefano Zampini 
762c2151214SStefano Zampini     /* map edge dofs connectivity */
7631e0482f5SStefano Zampini     if (jj) {
7649566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj));
765c2151214SStefano Zampini       for (i=0;i<ne;i++) {
766c2151214SStefano Zampini         PetscInt e = idxs[i];
767c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
768c2151214SStefano Zampini       }
7691e0482f5SStefano Zampini     }
7709566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(nedfieldlocal,&idxs));
7719566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER));
772c2151214SStefano Zampini     if (rest) {
7739566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done));
774c2151214SStefano Zampini     }
7751baa6e33SBarry Smith     if (free) PetscCall(PetscFree2(iiu,jju));
7769566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&btf));
777c2151214SStefano Zampini   } else {
7789566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER));
779c2151214SStefano Zampini   }
780c2151214SStefano Zampini 
781a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
7829566063dSJacob Faibussowitsch   PetscCall(PCBDDCAnalyzeInterface(pc));
783213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
784a13144ffSStefano Zampini 
785a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
7869566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals));
7879566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
788a13144ffSStefano Zampini 
789c2151214SStefano Zampini   if (fl2g) {
7909566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals));
7919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nee,&eedges));
792c2151214SStefano Zampini     for (i=0;i<nee;i++) {
7939566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]));
794c2151214SStefano Zampini     }
795c2151214SStefano Zampini   } else {
796c2151214SStefano Zampini     eedges  = alleedges;
797c2151214SStefano Zampini     primals = allprimals;
798c2151214SStefano Zampini   }
799c2151214SStefano Zampini 
800a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
8019566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(marks,ne));
8029566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(primals,&cum));
8039566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(primals,&idxs));
804c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
8059566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(primals,&idxs));
806c2151214SStefano Zampini   if (print) {
8079566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs"));
8089566063dSJacob Faibussowitsch     PetscCall(ISView(primals,NULL));
809c2151214SStefano Zampini   }
810c2151214SStefano Zampini 
811c2151214SStefano Zampini   maxsize = 0;
812a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
813a13144ffSStefano Zampini     PetscInt size,mark = i+1;
814a13144ffSStefano Zampini 
8159566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(eedges[i],&size));
8169566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(eedges[i],&idxs));
817a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
8189566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(eedges[i],&idxs));
819a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
820a13144ffSStefano Zampini   }
821a13144ffSStefano Zampini 
822a13144ffSStefano Zampini   /* Find coarse edge endpoints */
8239566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
8249566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
825a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
826a13144ffSStefano Zampini     PetscInt mark = i+1,size;
827a13144ffSStefano Zampini 
8289566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(eedges[i],&size));
8291e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
83063a3b9bcSJacob Faibussowitsch     PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %" PetscInt_FMT,i);
8319566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(eedges[i],&idxs));
832a13144ffSStefano Zampini     if (print) {
83363a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %" PetscInt_FMT "\n",i));
8349566063dSJacob Faibussowitsch       PetscCall(ISView(eedges[i],NULL));
835a13144ffSStefano Zampini     }
836a13144ffSStefano Zampini     for (j=0;j<size;j++) {
837a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
83863a3b9bcSJacob Faibussowitsch       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %" PetscInt_FMT "\n",ee);
839a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
84063a3b9bcSJacob Faibussowitsch         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %" PetscInt_FMT "\n",jj[k]);
841a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
84263a3b9bcSJacob Faibussowitsch           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %" PetscInt_FMT "\n",jj[k]);
843a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
844a13144ffSStefano Zampini           PetscInt  k2;
845a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
846a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
84763a3b9bcSJacob Faibussowitsch             if (print) PetscPrintf(PETSC_COMM_SELF,"        INSPECTING %" PetscInt_FMT ": mark %" PetscInt_FMT " (ref mark %" PetscInt_FMT "), boundary %d\n",jjt[k2],marks[jjt[k2]],mark,(int)!!PetscBTLookup(btb,jjt[k2]));
848c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
849c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
850c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
851a13144ffSStefano Zampini               corner = PETSC_TRUE;
852a13144ffSStefano Zampini               break;
853a13144ffSStefano Zampini             }
854a13144ffSStefano Zampini           }
855a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
85663a3b9bcSJacob Faibussowitsch             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %" PetscInt_FMT "\n",jj[k]);
8579566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(btv,jj[k]));
858a13144ffSStefano Zampini           } else {
859a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
860a13144ffSStefano Zampini           }
861a13144ffSStefano Zampini         }
862a13144ffSStefano Zampini       }
863a13144ffSStefano Zampini     }
8649566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(eedges[i],&idxs));
865a13144ffSStefano Zampini   }
8669566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
8679566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
8689566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btb));
869a13144ffSStefano Zampini 
870a13144ffSStefano Zampini   /* Reset marked primal dofs */
8719566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(primals,&cum));
8729566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(primals,&idxs));
873a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
8749566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(primals,&idxs));
875a13144ffSStefano Zampini 
8760569b399SStefano Zampini   /* Now use the initial lG */
8779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lG));
8789566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lGt));
8790569b399SStefano Zampini   lG   = lGinit;
8809566063dSJacob Faibussowitsch   PetscCall(MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt));
8810569b399SStefano Zampini 
882a13144ffSStefano Zampini   /* Compute extended cols indices */
8839566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nv,&btvc));
8849566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nee,&bter));
8859566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
8869566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetMaxRowNonzeros(lG,&i));
887a13144ffSStefano Zampini   i   *= maxsize;
8889566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nee,&extcols));
8899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(i,&extrow,i,&gidxs));
890a13144ffSStefano Zampini   eerr = PETSC_FALSE;
891a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
892b03ebc13SStefano Zampini     PetscInt size,found = 0;
893a13144ffSStefano Zampini 
894a13144ffSStefano Zampini     cum  = 0;
8959566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(eedges[i],&size));
8961e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
89763a3b9bcSJacob Faibussowitsch     PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %" PetscInt_FMT,i);
8989566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(eedges[i],&idxs));
8999566063dSJacob Faibussowitsch     PetscCall(PetscBTMemzero(nv,btvc));
900a13144ffSStefano Zampini     for (j=0;j<size;j++) {
901a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
902b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
903b03ebc13SStefano Zampini         PetscInt vv = jj[k];
904b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
905b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
906b03ebc13SStefano Zampini       }
907a13144ffSStefano Zampini     }
9089566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(eedges[i],&idxs));
9099566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsInt(&cum,extrow));
9109566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs));
9119566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(cum,gidxs,extrow));
9129566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]));
913a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
914a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
915b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
9169566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(bter,i));
917a13144ffSStefano Zampini       if (print) {
9189566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)eedges[i],"error_edge"));
9199566063dSJacob Faibussowitsch         PetscCall(ISView(eedges[i],NULL));
9209566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)extcols[i],"error_extcol"));
9219566063dSJacob Faibussowitsch         PetscCall(ISView(extcols[i],NULL));
922a13144ffSStefano Zampini       }
923a13144ffSStefano Zampini       eerr = PETSC_TRUE;
924a13144ffSStefano Zampini     }
925a13144ffSStefano Zampini   }
92628b400f6SJacob Faibussowitsch   /* PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
9271c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm));
928a13144ffSStefano Zampini   if (done) {
929a13144ffSStefano Zampini     PetscInt *newprimals;
930a13144ffSStefano Zampini 
9319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ne,&newprimals));
9329566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(primals,&cum));
9339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(primals,&idxs));
9349566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(newprimals,idxs,cum));
9359566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(primals,&idxs));
9369566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
93763a3b9bcSJacob Faibussowitsch     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %s)\n",PetscBools[eerr]);
938a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
939b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
940b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
941a13144ffSStefano Zampini         PetscInt size,mark = i+1;
942a13144ffSStefano Zampini 
9439566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(eedges[i],&size));
9449566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(eedges[i],&idxs));
945c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
946a13144ffSStefano Zampini         for (j=0;j<size;j++) {
947a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
94863a3b9bcSJacob Faibussowitsch           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %" PetscInt_FMT " [%" PetscInt_FMT " %" PetscInt_FMT ")\n",ee,ii[ee],ii[ee+1]);
949a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
950a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
951a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
952a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
953b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
95463a3b9bcSJacob Faibussowitsch               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %" PetscInt_FMT "\n",vv);
9559566063dSJacob Faibussowitsch               PetscCall(PetscBTSet(btv,vv));
956a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
957a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
958a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
959a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
96063a3b9bcSJacob Faibussowitsch                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %" PetscInt_FMT "\n",ee2);
961a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
962a13144ffSStefano Zampini                   /* finally set the new corners */
963a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
96463a3b9bcSJacob Faibussowitsch                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %" PetscInt_FMT "\n",jj[k3]);
9659566063dSJacob Faibussowitsch                     PetscCall(PetscBTSet(btv,jj[k3]));
966a13144ffSStefano Zampini                   }
967a13144ffSStefano Zampini                 }
968a13144ffSStefano Zampini               }
969b03ebc13SStefano Zampini             } else {
97063a3b9bcSJacob Faibussowitsch               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %" PetscInt_FMT "\n",jj[k]);
971a13144ffSStefano Zampini             }
972a13144ffSStefano Zampini           }
973a13144ffSStefano Zampini         }
974b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
975b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
976b03ebc13SStefano Zampini 
9779566063dSJacob Faibussowitsch           PetscCall(PetscCalloc1(ne,&tmarks));
97863a3b9bcSJacob Faibussowitsch           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %" PetscInt_FMT "\n",i);
979b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
980b03ebc13SStefano Zampini             PetscInt k2;
98163a3b9bcSJacob Faibussowitsch             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %" PetscInt_FMT "\n",jj[k]);
9829566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(btv,jj[k]));
983b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
984b03ebc13SStefano Zampini           }
985b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
986b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
98763a3b9bcSJacob Faibussowitsch               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %" PetscInt_FMT "\n",idxs[j]);
988b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
989b03ebc13SStefano Zampini             }
990b03ebc13SStefano Zampini           }
9919566063dSJacob Faibussowitsch           PetscCall(PetscFree(tmarks));
992b03ebc13SStefano Zampini         }
9939566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(eedges[i],&idxs));
994a13144ffSStefano Zampini       }
9959566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&extcols[i]));
996a13144ffSStefano Zampini     }
9979566063dSJacob Faibussowitsch     PetscCall(PetscFree(extcols));
9989566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
9999566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsInt(&cum,newprimals));
1000c2151214SStefano Zampini     if (fl2g) {
10019566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals));
10029566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&primals));
1003c2151214SStefano Zampini       for (i=0;i<nee;i++) {
10049566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&eedges[i]));
1005c2151214SStefano Zampini       }
10069566063dSJacob Faibussowitsch       PetscCall(PetscFree(eedges));
1007c2151214SStefano Zampini     }
10089566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals));
10099566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals));
10109566063dSJacob Faibussowitsch     PetscCall(PetscFree(newprimals));
10119566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc,primals));
10129566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&primals));
10139566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
1014213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
10159566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals));
1016c2151214SStefano Zampini     if (fl2g) {
10179566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals));
10189566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nee,&eedges));
1019c2151214SStefano Zampini       for (i=0;i<nee;i++) {
10209566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]));
1021c2151214SStefano Zampini       }
1022c2151214SStefano Zampini     } else {
1023c2151214SStefano Zampini       eedges  = alleedges;
1024c2151214SStefano Zampini       primals = allprimals;
1025c2151214SStefano Zampini     }
10269566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nee,&extcols));
1027a13144ffSStefano Zampini 
1028a13144ffSStefano Zampini     /* Mark again */
10299566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(marks,ne));
1030a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1031a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1032a13144ffSStefano Zampini 
10339566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(eedges[i],&size));
10349566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(eedges[i],&idxs));
1035a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
10369566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(eedges[i],&idxs));
1037a13144ffSStefano Zampini     }
1038a13144ffSStefano Zampini     if (print) {
10399566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass"));
10409566063dSJacob Faibussowitsch       PetscCall(ISView(primals,NULL));
1041a13144ffSStefano Zampini     }
1042a13144ffSStefano Zampini 
1043a13144ffSStefano Zampini     /* Recompute extended cols */
1044a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1045a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1046a13144ffSStefano Zampini       PetscInt size;
1047a13144ffSStefano Zampini 
1048a13144ffSStefano Zampini       cum  = 0;
10499566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(eedges[i],&size));
10501e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
105163a3b9bcSJacob Faibussowitsch       PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %" PetscInt_FMT,i);
10529566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(eedges[i],&idxs));
1053a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1054a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10551e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1056a13144ffSStefano Zampini       }
10579566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(eedges[i],&idxs));
10589566063dSJacob Faibussowitsch       PetscCall(PetscSortRemoveDupsInt(&cum,extrow));
10599566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs));
10609566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithArray(cum,gidxs,extrow));
10619566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]));
1062a13144ffSStefano Zampini       if (cum != size -1) {
1063a13144ffSStefano Zampini         if (print) {
10649566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass"));
10659566063dSJacob Faibussowitsch           PetscCall(ISView(eedges[i],NULL));
10669566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass"));
10679566063dSJacob Faibussowitsch           PetscCall(ISView(extcols[i],NULL));
1068a13144ffSStefano Zampini         }
1069a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1070a13144ffSStefano Zampini       }
1071a13144ffSStefano Zampini     }
1072a13144ffSStefano Zampini   }
10739566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
10749566063dSJacob Faibussowitsch   PetscCall(PetscFree2(extrow,gidxs));
10759566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&bter));
10769566063dSJacob Faibussowitsch   if (print) PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF));
1077a13144ffSStefano Zampini   /* an error should not occur at this point */
107828b400f6SJacob Faibussowitsch   PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1079a13144ffSStefano Zampini 
10804e64d54eSstefano_zampini   /* Check the number of endpoints */
10819566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
10829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2*nee,&corners));
10839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nee,&cedges));
10844e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1085b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
10864e64d54eSstefano_zampini 
1087b03ebc13SStefano Zampini     /* init with defaults */
1088b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
10899566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(eedges[i],&size));
10901e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
109163a3b9bcSJacob Faibussowitsch     PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %" PetscInt_FMT,i);
10929566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(eedges[i],&idxs));
10939566063dSJacob Faibussowitsch     PetscCall(PetscBTMemzero(nv,btvc));
10944e64d54eSstefano_zampini     for (j=0;j<size;j++) {
10954e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
10964e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
10974e64d54eSstefano_zampini         PetscInt vv = jj[k];
10984e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
109963a3b9bcSJacob Faibussowitsch           PetscCheck(found != 2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %" PetscInt_FMT,i);
1100b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11014e64d54eSstefano_zampini         }
11024e64d54eSstefano_zampini       }
11034e64d54eSstefano_zampini     }
1104b03ebc13SStefano Zampini     if (found != 2) {
1105b03ebc13SStefano Zampini       PetscInt e;
1106b03ebc13SStefano Zampini       if (fl2g) {
11079566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingApply(fl2g,1,idxs,&e));
1108b03ebc13SStefano Zampini       } else {
1109b03ebc13SStefano Zampini         e = idxs[0];
1110b03ebc13SStefano Zampini       }
111163a3b9bcSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %" PetscInt_FMT " corners for edge %" PetscInt_FMT " (astart %" PetscInt_FMT ", estart %" PetscInt_FMT ")",found,i,e,idxs[0]);
1112b03ebc13SStefano Zampini     }
1113eee23b56SStefano Zampini 
1114eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
11159566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc));
1116b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1117b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1118b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1119b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1120b03ebc13SStefano Zampini     }
1121eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11229566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(eedges[i],&idxs));
112363a3b9bcSJacob Faibussowitsch     if (print) PetscPrintf(PETSC_COMM_SELF,"EDGE %" PetscInt_FMT ": ce %" PetscInt_FMT ", corners (%" PetscInt_FMT ",%" PetscInt_FMT ")\n",i,cedges[i],corners[2*i],corners[2*i+1]);
11244e64d54eSstefano_zampini   }
11259566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
11269566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btvc));
11274e64d54eSstefano_zampini 
112876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1129a13144ffSStefano Zampini     /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1130a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
11319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nee+1,&emarks));
11329566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
1133a13144ffSStefano Zampini     for (i=0;i<nv;i++) {
1134a13144ffSStefano Zampini       PetscInt emax = 0,eemax = 0;
1135a13144ffSStefano Zampini 
1136a13144ffSStefano Zampini       if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
11379566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(emarks,nee+1));
1138a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1139a13144ffSStefano Zampini       for (j=1;j<nee+1;j++) {
1140a13144ffSStefano Zampini         if (emax < emarks[j]) {
1141a13144ffSStefano Zampini           emax = emarks[j];
1142a13144ffSStefano Zampini           eemax = j;
1143a13144ffSStefano Zampini         }
1144a13144ffSStefano Zampini       }
1145a13144ffSStefano Zampini       /* not relevant for edges */
1146a13144ffSStefano Zampini       if (!eemax) continue;
1147a13144ffSStefano Zampini 
1148a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
1149a13144ffSStefano Zampini         if (marks[jj[j]] && marks[jj[j]] != eemax) {
115063a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Found 2 coarse edges (id %" PetscInt_FMT " and %" PetscInt_FMT ") connected through the %" PetscInt_FMT " nodal dof at edge dof %" PetscInt_FMT,marks[jj[j]]-1,eemax,i,jj[j]);
1151a13144ffSStefano Zampini         }
1152a13144ffSStefano Zampini       }
1153a13144ffSStefano Zampini     }
11549566063dSJacob Faibussowitsch     PetscCall(PetscFree(emarks));
11559566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
115676bd3646SJed Brown   }
1157a13144ffSStefano Zampini 
1158a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
11599566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
11609566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetMaxRowNonzeros(lGt,&extmem));
1161a13144ffSStefano Zampini   extmem *= maxsize;
11629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(extmem*nee,&extrow));
11639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nee,&extrows));
11649566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nee,&extrowcum));
1165a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1166a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1167213b8bfaSStefano Zampini 
1168a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1169a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1170a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1171a13144ffSStefano Zampini         mark = marks[jj[j]];
1172a13144ffSStefano Zampini 
1173a13144ffSStefano Zampini     /* not relevant */
1174a13144ffSStefano Zampini     if (!mark) continue;
1175a13144ffSStefano Zampini 
1176a13144ffSStefano Zampini     /* import extended row */
1177a13144ffSStefano Zampini     mark--;
1178a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1179a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
118063a3b9bcSJacob Faibussowitsch     PetscCheck(extrowcum[mark] + size <= extmem,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %" PetscInt_FMT " > %" PetscInt_FMT,extrowcum[mark] + size,extmem);
11819566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(extrow+start,jj+ii[i],size));
1182a13144ffSStefano Zampini     extrowcum[mark] += size;
1183a13144ffSStefano Zampini   }
11849566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
11859566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lGt));
11869566063dSJacob Faibussowitsch   PetscCall(PetscFree(marks));
1187213b8bfaSStefano Zampini 
1188213b8bfaSStefano Zampini   /* Compress extrows */
1189a13144ffSStefano Zampini   cum  = 0;
1190a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1191a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
11929566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsInt(&size,start));
11939566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]));
1194a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1195a13144ffSStefano Zampini   }
11969566063dSJacob Faibussowitsch   PetscCall(PetscFree(extrowcum));
11979566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btv));
11989566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btvcand));
1199a13144ffSStefano Zampini 
1200a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
12019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork));
1202a13144ffSStefano Zampini 
1203a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
12049566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,&T));
1205d0609cedSBarry Smith   PetscCall(MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,pc->pmat->rmap->N,pc->pmat->rmap->N));
12069566063dSJacob Faibussowitsch   PetscCall(MatSetType(T,MATAIJ));
12079566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(T,10,NULL));
12089566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(T,10,NULL,10,NULL));
12099566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(T,al2g,al2g));
12109566063dSJacob Faibussowitsch   PetscCall(MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE));
12119566063dSJacob Faibussowitsch   PetscCall(MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE));
12129566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&al2g));
1213a13144ffSStefano Zampini 
1214a13144ffSStefano Zampini   /* Defaults to identity */
12159566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat,&tvec,NULL));
12169566063dSJacob Faibussowitsch   PetscCall(VecSet(tvec,1.0));
12179566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet(T,tvec,INSERT_VALUES));
12189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tvec));
1219a13144ffSStefano Zampini 
12201e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12219566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->nedcG));
12229566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->nedclocal));
12231e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12241e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12251e0482f5SStefano Zampini     IS                     wis,gwis;
12261e0482f5SStefano Zampini     PetscInt               cnv,cne;
12271e0482f5SStefano Zampini 
12289566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis));
12291e0482f5SStefano Zampini     if (fl2g) {
12309566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal));
12311e0482f5SStefano Zampini     } else {
12329566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)wis));
12331e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12341e0482f5SStefano Zampini     }
12359566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis));
12369566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&wis));
12379566063dSJacob Faibussowitsch     PetscCall(ISRenumber(gwis,NULL,&cne,&wis));
12389566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(wis,&cel2g));
12399566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&wis));
12409566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gwis));
12411e0482f5SStefano Zampini 
12429566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis));
12439566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis));
12449566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&wis));
12459566063dSJacob Faibussowitsch     PetscCall(ISRenumber(gwis,NULL,&cnv,&wis));
12469566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(wis,&cvl2g));
12479566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&wis));
12489566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gwis));
12491e0482f5SStefano Zampini 
12509566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,&pcbddc->nedcG));
12519566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv));
12529566063dSJacob Faibussowitsch     PetscCall(MatSetType(pcbddc->nedcG,MATAIJ));
12539566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL));
12549566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL));
12559566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g));
12569566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cel2g));
12579566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cvl2g));
12581e0482f5SStefano Zampini   }
12599566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&vl2g));
12601e0482f5SStefano Zampini 
12611e0482f5SStefano Zampini #if defined(PRINT_GDET)
12621e0482f5SStefano Zampini   inc = 0;
12631e0482f5SStefano Zampini   lev = pcbddc->current_level;
12641e0482f5SStefano Zampini #endif
1265213b8bfaSStefano Zampini 
1266213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1267a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1268a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12691e0482f5SStefano Zampini     IS          cornersis = NULL;
12701e0482f5SStefano Zampini     PetscScalar cvals[2];
1271a13144ffSStefano Zampini 
12721e0482f5SStefano Zampini     if (pcbddc->nedcG) {
12739566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis));
12741e0482f5SStefano Zampini     }
12759566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork));
1276a13144ffSStefano Zampini     if (Gins && GKins) {
12771683a169SBarry Smith       const PetscScalar *data;
1278a13144ffSStefano Zampini       const PetscInt    *rows,*cols;
1279a13144ffSStefano Zampini       PetscInt          nrh,nch,nrc,ncc;
1280a13144ffSStefano Zampini 
12819566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(eedges[i],&cols));
1282a13144ffSStefano Zampini       /* H1 */
12839566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(extrows[i],&rows));
12849566063dSJacob Faibussowitsch       PetscCall(MatGetSize(Gins,&nrh,&nch));
12859566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(Gins,&data));
12869566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES));
12879566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(Gins,&data));
12889566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(extrows[i],&rows));
1289a13144ffSStefano Zampini       /* complement */
12909566063dSJacob Faibussowitsch       PetscCall(MatGetSize(GKins,&nrc,&ncc));
129163a3b9bcSJacob Faibussowitsch       PetscCheck(ncc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %" PetscInt_FMT,i);
129263a3b9bcSJacob Faibussowitsch       PetscCheck(ncc + nch == nrc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"The sum of the number of columns of GKins %" PetscInt_FMT " and Gins %" PetscInt_FMT " does not match %" PetscInt_FMT " for coarse edge %" PetscInt_FMT,ncc,nch,nrc,i);
129363a3b9bcSJacob Faibussowitsch       PetscCheck(ncc == 1 || !pcbddc->nedcG,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot generate the coarse discrete gradient for coarse edge %" PetscInt_FMT " with ncc %" PetscInt_FMT,i,ncc);
12949566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(GKins,&data));
12959566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES));
12969566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(GKins,&data));
12971e0482f5SStefano Zampini 
12981e0482f5SStefano Zampini       /* coarse discrete gradient */
12991e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13001e0482f5SStefano Zampini         PetscInt cols[2];
13011e0482f5SStefano Zampini 
13021e0482f5SStefano Zampini         cols[0] = 2*i;
13031e0482f5SStefano Zampini         cols[1] = 2*i+1;
13049566063dSJacob Faibussowitsch         PetscCall(MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES));
13051e0482f5SStefano Zampini       }
13069566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(eedges[i],&cols));
1307a13144ffSStefano Zampini     }
13089566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&extrows[i]));
13099566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&extcols[i]));
13109566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cornersis));
13119566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Gins));
13129566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&GKins));
1313a13144ffSStefano Zampini   }
13149566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&el2g));
1315a13144ffSStefano Zampini 
1316a13144ffSStefano Zampini   /* Start assembling */
13179566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY));
13181baa6e33SBarry Smith   if (pcbddc->nedcG) PetscCall(MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY));
1319a13144ffSStefano Zampini 
1320a13144ffSStefano Zampini   /* Free */
1321c2151214SStefano Zampini   if (fl2g) {
13229566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&primals));
1323c2151214SStefano Zampini     for (i=0;i<nee;i++) {
13249566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&eedges[i]));
1325c2151214SStefano Zampini     }
13269566063dSJacob Faibussowitsch     PetscCall(PetscFree(eedges));
1327c2151214SStefano Zampini   }
1328eee23b56SStefano Zampini 
1329eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1330eee23b56SStefano Zampini   {
1331eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1332eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1333eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1334eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1335eee23b56SStefano Zampini 
1336eee23b56SStefano Zampini     /* find first primal edge */
1337eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
13389566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs));
1339eee23b56SStefano Zampini     } else {
13401baa6e33SBarry Smith       if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges));
1341eee23b56SStefano Zampini       idxs = cedges;
1342eee23b56SStefano Zampini     }
1343eee23b56SStefano Zampini     cum = 0;
1344eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1345eee23b56SStefano Zampini 
1346eee23b56SStefano Zampini     /* adapt connected components */
13479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue));
1348eee23b56SStefano Zampini     graph->cptr[0] = 0;
1349eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1350eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1351eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1352eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1353eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1354eee23b56SStefano Zampini         ncc++;
1355eee23b56SStefano Zampini         lc--;
1356eee23b56SStefano Zampini         cum++;
1357eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1358eee23b56SStefano Zampini       }
1359eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1360eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1361eee23b56SStefano Zampini       ncc++;
1362eee23b56SStefano Zampini     }
1363eee23b56SStefano Zampini     graph->ncc = ncc;
1364eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
13659566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs));
1366eee23b56SStefano Zampini     }
13679566063dSJacob Faibussowitsch     PetscCall(PetscFree2(ocptr,oqueue));
1368eee23b56SStefano Zampini   }
13699566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&fl2g));
13709566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals));
13719566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphResetCSR(pcbddc->mat_graph));
13729566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&conn));
1373eee23b56SStefano Zampini 
13749566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&nedfieldlocal));
13759566063dSJacob Faibussowitsch   PetscCall(PetscFree(extrow));
13769566063dSJacob Faibussowitsch   PetscCall(PetscFree2(work,rwork));
13779566063dSJacob Faibussowitsch   PetscCall(PetscFree(corners));
13789566063dSJacob Faibussowitsch   PetscCall(PetscFree(cedges));
13799566063dSJacob Faibussowitsch   PetscCall(PetscFree(extrows));
13809566063dSJacob Faibussowitsch   PetscCall(PetscFree(extcols));
13819566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lG));
1382a13144ffSStefano Zampini 
1383a13144ffSStefano Zampini   /* Complete assembling */
13849566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY));
13851e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13869566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY));
13871e0482f5SStefano Zampini #if 0
13889566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G"));
13899566063dSJacob Faibussowitsch     PetscCall(MatView(pcbddc->nedcG,NULL));
13901e0482f5SStefano Zampini #endif
13911e0482f5SStefano Zampini   }
1392a13144ffSStefano Zampini 
1393a13144ffSStefano Zampini   /* set change of basis */
13949566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetChangeOfBasisMat(pc,T,singular));
13959566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&T));
1396a13144ffSStefano Zampini 
1397a13144ffSStefano Zampini   PetscFunctionReturn(0);
1398a13144ffSStefano Zampini }
1399a13144ffSStefano Zampini 
1400d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1401d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1402d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1403d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1404d8203eabSStefano Zampini {
1405d8203eabSStefano Zampini   PetscInt       i;
1406d8203eabSStefano Zampini 
1407d8203eabSStefano Zampini   PetscFunctionBegin;
1408d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1409d8203eabSStefano Zampini     PetscInt first,last;
1410d8203eabSStefano Zampini 
14119566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(quad_vecs[i],&first,&last));
14127827d75bSBarry Smith     PetscCheck(last-first >= 2*nvecs || !has_const,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1413d8203eabSStefano Zampini     if (i>=first && i < last) {
1414d8203eabSStefano Zampini       PetscScalar *data;
14159566063dSJacob Faibussowitsch       PetscCall(VecGetArray(quad_vecs[i],&data));
1416d8203eabSStefano Zampini       if (!has_const) {
1417d8203eabSStefano Zampini         data[i-first] = 1.;
1418d8203eabSStefano Zampini       } else {
141986fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
142086fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1421d8203eabSStefano Zampini       }
14229566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(quad_vecs[i],&data));
1423d8203eabSStefano Zampini     }
14249566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i]));
1425d8203eabSStefano Zampini   }
14269566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp));
1427d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1428d8203eabSStefano Zampini     PetscInt first,last;
14299566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(quad_vecs[i]));
14309566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(quad_vecs[i],&first,&last));
1431d8203eabSStefano Zampini     if (i>=first && i < last) {
1432d8203eabSStefano Zampini       PetscScalar *data;
14339566063dSJacob Faibussowitsch       PetscCall(VecGetArray(quad_vecs[i],&data));
1434d8203eabSStefano Zampini       if (!has_const) {
1435d8203eabSStefano Zampini         data[i-first] = 0.;
1436d8203eabSStefano Zampini       } else {
143786fa73c5SStefano Zampini         data[2*i-first] = 0.;
143886fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1439d8203eabSStefano Zampini       }
14409566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(quad_vecs[i],&data));
1441d8203eabSStefano Zampini     }
14429566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i]));
14439566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(quad_vecs[i]));
1444d8203eabSStefano Zampini   }
1445d8203eabSStefano Zampini   PetscFunctionReturn(0);
1446d8203eabSStefano Zampini }
1447d8203eabSStefano Zampini 
14488ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1449669cc0f4SStefano Zampini {
1450a198735bSStefano Zampini   Mat                    loc_divudotp;
1451fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14528ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1453669cc0f4SStefano Zampini   PetscScalar            *vals;
1454669cc0f4SStefano Zampini   const PetscScalar      *array;
14550f04eeffSStefano Zampini   PetscInt               i,maxneighs = 0,maxsize,*gidxs;
1456a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
14571ae86dd6SStefano Zampini   PetscMPIInt            rank;
1458669cc0f4SStefano Zampini 
1459669cc0f4SStefano Zampini   PetscFunctionBegin;
14609566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared));
14610f04eeffSStefano Zampini   for (i=0;i<n_neigh;i++) maxneighs = PetscMax(graph->count[shared[i][0]]+1,maxneighs);
14621c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(MPI_IN_PLACE,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A)));
14638037d520SStefano Zampini   if (!maxneighs) {
14649566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared));
14658037d520SStefano Zampini     *nnsp = NULL;
14668037d520SStefano Zampini     PetscFunctionReturn(0);
1467669cc0f4SStefano Zampini   }
1468669cc0f4SStefano Zampini   maxsize = 0;
1469a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
14709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(maxsize,&gidxs,maxsize,&vals));
1471669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
14729566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A,&quad_vec,NULL));
14738ae0ca82SStefano Zampini   if (!transpose) {
14749566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(A,&map,NULL));
14758ae0ca82SStefano Zampini   } else {
14769566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(A,NULL,&map));
14778ae0ca82SStefano Zampini   }
14789566063dSJacob Faibussowitsch   PetscCall(VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs));
14799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&quad_vec));
14809566063dSJacob Faibussowitsch   PetscCall(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp));
1481669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
14829566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(quad_vecs[i]));
1483669cc0f4SStefano Zampini   }
1484d8203eabSStefano Zampini 
1485669cc0f4SStefano Zampini   /* compute local quad vec */
14869566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(divudotp,&loc_divudotp));
14878ae0ca82SStefano Zampini   if (!transpose) {
14889566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(loc_divudotp,&v,&p));
14898ae0ca82SStefano Zampini   } else {
14909566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(loc_divudotp,&p,&v));
14918ae0ca82SStefano Zampini   }
14929566063dSJacob Faibussowitsch   PetscCall(VecSet(p,1.));
14938ae0ca82SStefano Zampini   if (!transpose) {
14949566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(loc_divudotp,p,v));
14958ae0ca82SStefano Zampini   } else {
14969566063dSJacob Faibussowitsch     PetscCall(MatMult(loc_divudotp,p,v));
14978ae0ca82SStefano Zampini   }
1498fa23a32eSStefano Zampini   if (vl2l) {
1499187c917aSStefano Zampini     Mat        lA;
1500187c917aSStefano Zampini     VecScatter sc;
1501187c917aSStefano Zampini 
15029566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(A,&lA));
15039566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(lA,&vins,NULL));
15049566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(v,NULL,vins,vl2l,&sc));
15059566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD));
15069566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD));
15079566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sc));
1508fa23a32eSStefano Zampini   } else {
1509fa23a32eSStefano Zampini     vins = v;
1510fa23a32eSStefano Zampini   }
15119566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(vins,&array));
15129566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&p));
15139a962809SStefano Zampini 
15141ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank));
15160f04eeffSStefano Zampini   for (i=1;i<n_neigh;i++) {
1517669cc0f4SStefano Zampini     const PetscInt    *idxs;
1518669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1519669cc0f4SStefano Zampini 
1520a040e873SStefano Zampini     idxs = shared[i];
1521a040e873SStefano Zampini     nn   = n_shared[i];
1522669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15239566063dSJacob Faibussowitsch     PetscCall(PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx));
1524669cc0f4SStefano Zampini     idx  = -(idx+1);
152563a3b9bcSJacob Faibussowitsch     PetscCheck(idx >= 0 && idx < maxneighs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid index %" PetscInt_FMT " not in [0,%" PetscInt_FMT ")",idx,maxneighs);
15269566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(map,nn,idxs,gidxs));
15279566063dSJacob Faibussowitsch     PetscCall(VecSetValues(quad_vecs[idx],nn,gidxs,vals,INSERT_VALUES));
1528669cc0f4SStefano Zampini   }
15299566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared));
15309566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(vins,&array));
1531fa23a32eSStefano Zampini   if (vl2l) {
15329566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vins));
1533fa23a32eSStefano Zampini   }
15349566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v));
15359566063dSJacob Faibussowitsch   PetscCall(PetscFree2(gidxs,vals));
1536669cc0f4SStefano Zampini 
1537669cc0f4SStefano Zampini   /* assemble near null space */
1538669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
15399566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(quad_vecs[i]));
1540669cc0f4SStefano Zampini   }
1541669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
15429566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(quad_vecs[i]));
15439566063dSJacob Faibussowitsch     PetscCall(VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view"));
15449566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(quad_vecs[i]));
1545669cc0f4SStefano Zampini   }
15469566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(maxneighs,&quad_vecs));
1547669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1548669cc0f4SStefano Zampini }
1549669cc0f4SStefano Zampini 
15507620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
15517620a527SStefano Zampini {
15527620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15537620a527SStefano Zampini 
15547620a527SStefano Zampini   PetscFunctionBegin;
15557620a527SStefano Zampini   if (primalv) {
15567620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
15577620a527SStefano Zampini       IS list[2], newp;
15587620a527SStefano Zampini 
15597620a527SStefano Zampini       list[0] = primalv;
15607620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
15619566063dSJacob Faibussowitsch       PetscCall(ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp));
15629566063dSJacob Faibussowitsch       PetscCall(ISSortRemoveDups(newp));
15639566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&list[1]));
15647620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
15657620a527SStefano Zampini     } else {
15669566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc,primalv));
15677620a527SStefano Zampini     }
15687620a527SStefano Zampini   }
15697620a527SStefano Zampini   PetscFunctionReturn(0);
15707620a527SStefano Zampini }
1571669cc0f4SStefano Zampini 
15721c7a958bSStefano Zampini static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx)
15731c7a958bSStefano Zampini {
15741c7a958bSStefano Zampini   PetscInt f, *comp  = (PetscInt *)ctx;
15751c7a958bSStefano Zampini 
15761c7a958bSStefano Zampini   PetscFunctionBegin;
15771c7a958bSStefano Zampini   for (f=0;f<Nf;f++) out[f] = X[*comp];
15781c7a958bSStefano Zampini   PetscFunctionReturn(0);
15791c7a958bSStefano Zampini }
1580674ae819SStefano Zampini 
15811f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
15821f4df5f7SStefano Zampini {
15831f4df5f7SStefano Zampini   Vec            local,global;
15841f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15851f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
15865c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
15871f4df5f7SStefano Zampini 
15881f4df5f7SStefano Zampini   PetscFunctionBegin;
1589d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");
15909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL));
1591d0609cedSBarry Smith   PetscOptionsEnd();
15921f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
15939566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat,&global,NULL));
15949566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(matis->A,&local,NULL));
15959566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(global,PETSC_TRUE));
15969566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(local,PETSC_TRUE));
15976a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
15986a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
15999566063dSJacob Faibussowitsch       PetscCall(MatGetBlockSize(pc->pmat,&pcbddc->vertex_size));
16006a8fc67bSStefano Zampini     }
16016a8fc67bSStefano Zampini     goto boundary;
16026a8fc67bSStefano Zampini   }
16035c5e10d6SStefano Zampini 
16041f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16051f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16061f4df5f7SStefano Zampini       PetscInt i;
16070c85b387SStefano Zampini 
16089566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal));
16091f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16100c85b387SStefano Zampini         PetscInt bs;
16110c85b387SStefano Zampini 
16129566063dSJacob Faibussowitsch         PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]));
16139566063dSJacob Faibussowitsch         PetscCall(ISGetBlockSize(pcbddc->ISForDofs[i],&bs));
16149566063dSJacob Faibussowitsch         PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs));
16159566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
16161f4df5f7SStefano Zampini       }
16171f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16181f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16199566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddc->ISForDofs));
16201f4df5f7SStefano Zampini     }
16211f4df5f7SStefano Zampini   } else {
162221ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
162321ef3d20SStefano Zampini       DM dm;
162421ef3d20SStefano Zampini 
16259566063dSJacob Faibussowitsch       PetscCall(MatGetDM(pc->pmat, &dm));
16264f819b78SStefano Zampini       if (!dm) {
16279566063dSJacob Faibussowitsch         PetscCall(PCGetDM(pc, &dm));
162821ef3d20SStefano Zampini       }
162921ef3d20SStefano Zampini       if (dm) {
163021ef3d20SStefano Zampini         IS      *fields;
163121ef3d20SStefano Zampini         PetscInt nf,i;
16320c85b387SStefano Zampini 
16339566063dSJacob Faibussowitsch         PetscCall(DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL));
16349566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nf,&pcbddc->ISForDofsLocal));
163521ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
16360c85b387SStefano Zampini           PetscInt bs;
16370c85b387SStefano Zampini 
16389566063dSJacob Faibussowitsch           PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]));
16399566063dSJacob Faibussowitsch           PetscCall(ISGetBlockSize(fields[i],&bs));
16409566063dSJacob Faibussowitsch           PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs));
16419566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&fields[i]));
164221ef3d20SStefano Zampini         }
16439566063dSJacob Faibussowitsch         PetscCall(PetscFree(fields));
164421ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
164521ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
164621ef3d20SStefano Zampini         PetscContainer   c;
164721ef3d20SStefano Zampini 
16489566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c));
164921ef3d20SStefano Zampini         if (c) {
165021ef3d20SStefano Zampini           MatISLocalFields lf;
16519566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c,(void**)&lf));
16529566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf));
165321ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16541f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
16559566063dSJacob Faibussowitsch           PetscCall(MatGetBlockSize(pc->pmat,&i));
165621ef3d20SStefano Zampini           if (i > 1) {
1657986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16589566063dSJacob Faibussowitsch             PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal));
16591f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16609566063dSJacob Faibussowitsch               PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]));
16611f4df5f7SStefano Zampini             }
16621f4df5f7SStefano Zampini           }
166321ef3d20SStefano Zampini         }
166421ef3d20SStefano Zampini       }
16657a0e7b2cSstefano_zampini     } else {
16667a0e7b2cSstefano_zampini       PetscInt i;
16677a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16689566063dSJacob Faibussowitsch         PetscCall(PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]));
16697a0e7b2cSstefano_zampini       }
16701f4df5f7SStefano Zampini     }
1671986cdee1SStefano Zampini   }
16721f4df5f7SStefano Zampini 
16735c5e10d6SStefano Zampini boundary:
16741f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16759566063dSJacob Faibussowitsch     PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal));
16767a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
16779566063dSJacob Faibussowitsch     PetscCall(PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal));
16781f4df5f7SStefano Zampini   }
16791f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16809566063dSJacob Faibussowitsch     PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal));
16817a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
16829566063dSJacob Faibussowitsch     PetscCall(PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal));
16831f4df5f7SStefano Zampini   }
16841f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16859566063dSJacob Faibussowitsch     PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local));
16861f4df5f7SStefano Zampini   }
16879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&global));
16889566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&local));
16897620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
16907620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
16917620a527SStefano Zampini     IS        primalv = NULL;
16927620a527SStefano Zampini     PetscInt  i;
16938361f951SStefano Zampini     PetscBool filter = pcbddc->detect_disconnected_filter;
16947a0e7b2cSstefano_zampini 
16957620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
16969566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pcbddc->local_subs[i]));
16977620a527SStefano Zampini     }
16989566063dSJacob Faibussowitsch     PetscCall(PetscFree(pcbddc->local_subs));
16999566063dSJacob Faibussowitsch     PetscCall(PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv));
17009566063dSJacob Faibussowitsch     PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc,primalv));
17019566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&primalv));
17027620a527SStefano Zampini   }
17037620a527SStefano Zampini   /* early stage corner detection */
17047620a527SStefano Zampini   {
17057620a527SStefano Zampini     DM dm;
17067620a527SStefano Zampini 
17079566063dSJacob Faibussowitsch     PetscCall(MatGetDM(pc->pmat,&dm));
17084f819b78SStefano Zampini     if (!dm) {
17099566063dSJacob Faibussowitsch       PetscCall(PCGetDM(pc,&dm));
17104f819b78SStefano Zampini     }
17117620a527SStefano Zampini     if (dm) {
17127620a527SStefano Zampini       PetscBool isda;
17137620a527SStefano Zampini 
17149566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda));
17157620a527SStefano Zampini       if (isda) {
17167620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17177620a527SStefano Zampini         IS                     corners;
17187620a527SStefano Zampini         Mat                    lA;
17194f819b78SStefano Zampini         PetscBool              gl,lo;
17207620a527SStefano Zampini 
17214f819b78SStefano Zampini         {
17224f819b78SStefano Zampini           Vec               cvec;
17234f819b78SStefano Zampini           const PetscScalar *coords;
17244f819b78SStefano Zampini           PetscInt          dof,n,cdim;
17254f819b78SStefano Zampini           PetscBool         memc = PETSC_TRUE;
17264f819b78SStefano Zampini 
17279566063dSJacob Faibussowitsch           PetscCall(DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL));
17289566063dSJacob Faibussowitsch           PetscCall(DMGetCoordinates(dm,&cvec));
17299566063dSJacob Faibussowitsch           PetscCall(VecGetLocalSize(cvec,&n));
17309566063dSJacob Faibussowitsch           PetscCall(VecGetBlockSize(cvec,&cdim));
17314f819b78SStefano Zampini           n   /= cdim;
17329566063dSJacob Faibussowitsch           PetscCall(PetscFree(pcbddc->mat_graph->coords));
17339566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(dof*n*cdim,&pcbddc->mat_graph->coords));
17349566063dSJacob Faibussowitsch           PetscCall(VecGetArrayRead(cvec,&coords));
17354f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
17364f819b78SStefano Zampini           memc = PETSC_FALSE;
17374f819b78SStefano Zampini #endif
17384f819b78SStefano Zampini           if (dof != 1) memc = PETSC_FALSE;
17394f819b78SStefano Zampini           if (memc) {
17409566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(pcbddc->mat_graph->coords,coords,cdim*n*dof));
17414f819b78SStefano Zampini           } else { /* BDDC graph does not use any blocked information, we need to replicate the data */
17424f819b78SStefano Zampini             PetscReal *bcoords = pcbddc->mat_graph->coords;
17434f819b78SStefano Zampini             PetscInt  i, b, d;
17444f819b78SStefano Zampini 
17454f819b78SStefano Zampini             for (i=0;i<n;i++) {
17464f819b78SStefano Zampini               for (b=0;b<dof;b++) {
17474f819b78SStefano Zampini                 for (d=0;d<cdim;d++) {
17484f819b78SStefano Zampini                   bcoords[i*dof*cdim + b*cdim + d] = PetscRealPart(coords[i*cdim+d]);
17494f819b78SStefano Zampini                 }
17504f819b78SStefano Zampini               }
17514f819b78SStefano Zampini             }
17524f819b78SStefano Zampini           }
17539566063dSJacob Faibussowitsch           PetscCall(VecRestoreArrayRead(cvec,&coords));
17544f819b78SStefano Zampini           pcbddc->mat_graph->cdim  = cdim;
17554f819b78SStefano Zampini           pcbddc->mat_graph->cnloc = dof*n;
17564f819b78SStefano Zampini           pcbddc->mat_graph->cloc  = PETSC_FALSE;
17574f819b78SStefano Zampini         }
17589566063dSJacob Faibussowitsch         PetscCall(DMDAGetSubdomainCornersIS(dm,&corners));
17599566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(pc->pmat,&lA));
17609566063dSJacob Faibussowitsch         PetscCall(MatGetLocalToGlobalMapping(lA,&l2l,NULL));
17619566063dSJacob Faibussowitsch         PetscCall(MatISRestoreLocalMat(pc->pmat,&lA));
17624f819b78SStefano Zampini         lo   = (PetscBool)(l2l && corners);
17631c2dc1cbSBarry Smith         PetscCall(MPIU_Allreduce(&lo,&gl,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc)));
17644f819b78SStefano Zampini         if (gl) { /* From PETSc's DMDA */
17657620a527SStefano Zampini           const PetscInt    *idx;
176672ed36d8SStefano Zampini           PetscInt          dof,bs,*idxout,n;
17677620a527SStefano Zampini 
17689566063dSJacob Faibussowitsch           PetscCall(DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL));
17699566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetBlockSize(l2l,&bs));
17709566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(corners,&n));
17719566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(corners,&idx));
177272ed36d8SStefano Zampini           if (bs == dof) {
17739566063dSJacob Faibussowitsch             PetscCall(PetscMalloc1(n,&idxout));
17749566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout));
177572ed36d8SStefano Zampini           } else { /* the original DMDA local-to-local map have been modified */
177672ed36d8SStefano Zampini             PetscInt i,d;
177772ed36d8SStefano Zampini 
17789566063dSJacob Faibussowitsch             PetscCall(PetscMalloc1(dof*n,&idxout));
177972ed36d8SStefano Zampini             for (i=0;i<n;i++) for (d=0;d<dof;d++) idxout[dof*i+d] = dof*idx[i]+d;
17809566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingApply(l2l,dof*n,idxout,idxout));
178172ed36d8SStefano Zampini 
178272ed36d8SStefano Zampini             bs = 1;
178372ed36d8SStefano Zampini             n *= dof;
178472ed36d8SStefano Zampini           }
17859566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(corners,&idx));
17869566063dSJacob Faibussowitsch           PetscCall(DMDARestoreSubdomainCornersIS(dm,&corners));
17879566063dSJacob Faibussowitsch           PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners));
17889566063dSJacob Faibussowitsch           PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc,corners));
17899566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&corners));
17901c7a958bSStefano Zampini           pcbddc->corner_selected  = PETSC_TRUE;
17914f819b78SStefano Zampini           pcbddc->corner_selection = PETSC_TRUE;
17924f819b78SStefano Zampini         }
17934f819b78SStefano Zampini         if (corners) {
17949566063dSJacob Faibussowitsch           PetscCall(DMDARestoreSubdomainCornersIS(dm,&corners));
17957620a527SStefano Zampini         }
17967620a527SStefano Zampini       }
17977620a527SStefano Zampini     }
17987620a527SStefano Zampini   }
17991c7a958bSStefano Zampini   if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) {
18001c7a958bSStefano Zampini     DM dm;
18011c7a958bSStefano Zampini 
18029566063dSJacob Faibussowitsch     PetscCall(MatGetDM(pc->pmat,&dm));
18034f819b78SStefano Zampini     if (!dm) {
18049566063dSJacob Faibussowitsch       PetscCall(PCGetDM(pc,&dm));
18051c7a958bSStefano Zampini     }
18064f819b78SStefano Zampini     if (dm) { /* this can get very expensive, I need to find a faster alternative */
18071c7a958bSStefano Zampini       Vec            vcoords;
18081c7a958bSStefano Zampini       PetscSection   section;
18091c7a958bSStefano Zampini       PetscReal      *coords;
18101c7a958bSStefano Zampini       PetscInt       d,cdim,nl,nf,**ctxs;
18111c7a958bSStefano Zampini       PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
181251ab8ad6SStefano Zampini       /* debug coordinates */
181351ab8ad6SStefano Zampini       PetscViewer       viewer;
181451ab8ad6SStefano Zampini       PetscBool         flg;
181551ab8ad6SStefano Zampini       PetscViewerFormat format;
181651ab8ad6SStefano Zampini       const char        *prefix;
18171c7a958bSStefano Zampini 
18189566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateDim(dm,&cdim));
18199566063dSJacob Faibussowitsch       PetscCall(DMGetLocalSection(dm,&section));
18209566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(section,&nf));
18219566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(dm,&vcoords));
18229566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(vcoords,&nl));
18239566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl*cdim,&coords));
18249566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(nf,&funcs,nf,&ctxs));
18259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nf,&ctxs[0]));
18261c7a958bSStefano Zampini       for (d=0;d<nf;d++) funcs[d] = func_coords_private;
18271c7a958bSStefano Zampini       for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1;
182851ab8ad6SStefano Zampini 
182951ab8ad6SStefano Zampini       /* debug coordinates */
183051ab8ad6SStefano Zampini       PetscCall(PCGetOptionsPrefix(pc,&prefix));
183151ab8ad6SStefano Zampini       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)vcoords),((PetscObject)vcoords)->options,prefix,"-pc_bddc_coords_vec_view",&viewer,&format,&flg));
183251ab8ad6SStefano Zampini       if (flg) PetscCall(PetscViewerPushFormat(viewer,format));
18331c7a958bSStefano Zampini       for (d=0;d<cdim;d++) {
18341c7a958bSStefano Zampini         PetscInt          i;
18351c7a958bSStefano Zampini         const PetscScalar *v;
183651ab8ad6SStefano Zampini         char              name[16];
18371c7a958bSStefano Zampini 
18381c7a958bSStefano Zampini         for (i=0;i<nf;i++) ctxs[i][0] = d;
183951ab8ad6SStefano Zampini         PetscCall(PetscSNPrintf(name,sizeof(name),"bddc_coords_%d",(int)d));
184051ab8ad6SStefano Zampini         PetscCall(PetscObjectSetName((PetscObject)vcoords,name));
18419566063dSJacob Faibussowitsch         PetscCall(DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords));
184251ab8ad6SStefano Zampini         if (flg) PetscCall(VecView(vcoords,viewer));
18439566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(vcoords,&v));
18441c7a958bSStefano Zampini         for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]);
18459566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(vcoords,&v));
18461c7a958bSStefano Zampini       }
18479566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&vcoords));
18489566063dSJacob Faibussowitsch       PetscCall(PCSetCoordinates(pc,cdim,nl,coords));
18499566063dSJacob Faibussowitsch       PetscCall(PetscFree(coords));
18509566063dSJacob Faibussowitsch       PetscCall(PetscFree(ctxs[0]));
18519566063dSJacob Faibussowitsch       PetscCall(PetscFree2(funcs,ctxs));
185251ab8ad6SStefano Zampini       if (flg) {
185351ab8ad6SStefano Zampini         PetscCall(PetscViewerPopFormat(viewer));
185451ab8ad6SStefano Zampini         PetscCall(PetscViewerDestroy(&viewer));
185551ab8ad6SStefano Zampini       }
18561c7a958bSStefano Zampini     }
18571c7a958bSStefano Zampini   }
18587a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
18597a0e7b2cSstefano_zampini }
18607a0e7b2cSstefano_zampini 
18617a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
18627a0e7b2cSstefano_zampini {
18637a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
18647a0e7b2cSstefano_zampini   IS              nis;
18657a0e7b2cSstefano_zampini   const PetscInt  *idxs;
18667a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
18677a0e7b2cSstefano_zampini 
18687a0e7b2cSstefano_zampini   PetscFunctionBegin;
18697827d75bSBarry Smith   PetscCheck(mop == MPI_LAND || mop == MPI_LOR,PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
18707a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18717a0e7b2cSstefano_zampini     /* init rootdata with true */
18721bd50df1SStefano Zampini     for (i=0;i<pc->pmat->rmap->n;i++) matis->sf_rootdata[i] = 1;
18737a0e7b2cSstefano_zampini   } else {
18749566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n));
18757a0e7b2cSstefano_zampini   }
18769566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_leafdata,n));
18779566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(*is,&nd));
18789566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(*is,&idxs));
18797a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18807a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18811bd50df1SStefano Zampini       matis->sf_leafdata[idxs[i]] = 1;
18829566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(*is,&idxs));
18839566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,mop));
18849566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,mop));
18859566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
18869566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
18877a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nd,&nidxs));
18897a0e7b2cSstefano_zampini   } else {
18909566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&nidxs));
18917a0e7b2cSstefano_zampini   }
18927a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
18931bd50df1SStefano Zampini     if (matis->sf_leafdata[i])
18947a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
18959566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis));
18969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(is));
18977a0e7b2cSstefano_zampini   *is  = nis;
18981f4df5f7SStefano Zampini   PetscFunctionReturn(0);
18991f4df5f7SStefano Zampini }
19001f4df5f7SStefano Zampini 
19013e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
19023e589ea0SStefano Zampini {
19033e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
19043e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
19053e589ea0SStefano Zampini 
19063e589ea0SStefano Zampini   PetscFunctionBegin;
19073e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
19083e589ea0SStefano Zampini     PetscFunctionReturn(0);
19093e589ea0SStefano Zampini   }
19103e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19113e589ea0SStefano Zampini     Vec swap;
19123e589ea0SStefano Zampini 
19139566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change));
19143e589ea0SStefano Zampini     swap = pcbddc->work_change;
19153e589ea0SStefano Zampini     pcbddc->work_change = r;
19163e589ea0SStefano Zampini     r = swap;
19173e589ea0SStefano Zampini   }
19189566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
19199566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
19209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19219566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
19229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19239566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
19249566063dSJacob Faibussowitsch   PetscCall(VecSet(z,0.));
19259566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
19269566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
19273e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1928f913dca9SStefano Zampini     pcbddc->work_change = r;
19299566063dSJacob Faibussowitsch     PetscCall(VecCopy(z,pcbddc->work_change));
19309566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z));
19313e589ea0SStefano Zampini   }
19323e589ea0SStefano Zampini   PetscFunctionReturn(0);
19333e589ea0SStefano Zampini }
19343e589ea0SStefano Zampini 
1935a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1936a3df083aSStefano Zampini {
1937a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1938a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1939a3df083aSStefano Zampini 
1940a3df083aSStefano Zampini   PetscFunctionBegin;
19419566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(A,&ctx));
1942a3df083aSStefano Zampini   if (transpose) {
1943a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1944a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1945a3df083aSStefano Zampini   } else {
1946a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1947a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1948a3df083aSStefano Zampini   }
1949a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1950a3df083aSStefano Zampini   if (apply_right) {
1951a3df083aSStefano Zampini     const PetscScalar *ax;
1952a3df083aSStefano Zampini     PetscInt          nl,i;
1953a3df083aSStefano Zampini 
19549566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(x,&nl));
19559566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&ax));
19569566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(ctx->work,ax,nl));
19579566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&ax));
1958a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1959a3df083aSStefano Zampini       PetscScalar    sum,val;
1960a3df083aSStefano Zampini       const PetscInt *idxs;
1961a3df083aSStefano Zampini       PetscInt       nz,j;
19629566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz));
19639566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs));
1964a3df083aSStefano Zampini       sum = 0.;
1965a3df083aSStefano Zampini       if (ctx->apply_p0) {
1966a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1967a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1968a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1969a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1970a3df083aSStefano Zampini         }
1971a3df083aSStefano Zampini       } else {
1972a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1973a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1974a3df083aSStefano Zampini         }
1975a3df083aSStefano Zampini       }
1976a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
19779566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs));
1978a3df083aSStefano Zampini     }
19799566063dSJacob Faibussowitsch     PetscCall(VecPlaceArray(x,ctx->work));
1980a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1981a3df083aSStefano Zampini   }
1982a3df083aSStefano Zampini   if (transpose) {
19839566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(ctx->A,x,y));
1984a3df083aSStefano Zampini   } else {
19859566063dSJacob Faibussowitsch     PetscCall(MatMult(ctx->A,x,y));
1986a3df083aSStefano Zampini   }
19871baa6e33SBarry Smith   if (reset_x) PetscCall(VecResetArray(x));
1988a3df083aSStefano Zampini   if (apply_left) {
1989a3df083aSStefano Zampini     PetscScalar *ay;
1990a3df083aSStefano Zampini     PetscInt    i;
1991a3df083aSStefano Zampini 
19929566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&ay));
1993a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1994a3df083aSStefano Zampini       PetscScalar    sum,val;
1995a3df083aSStefano Zampini       const PetscInt *idxs;
1996a3df083aSStefano Zampini       PetscInt       nz,j;
19979566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz));
19989566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs));
1999a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
2000a3df083aSStefano Zampini       if (ctx->apply_p0) {
2001a3df083aSStefano Zampini         sum = 0.;
2002a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2003a3df083aSStefano Zampini           sum += ay[idxs[j]];
2004a3df083aSStefano Zampini           ay[idxs[j]] += val;
2005a3df083aSStefano Zampini         }
2006a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
2007a3df083aSStefano Zampini       } else {
2008a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2009a3df083aSStefano Zampini           ay[idxs[j]] += val;
2010a3df083aSStefano Zampini         }
2011a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
2012a3df083aSStefano Zampini       }
20139566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs));
2014a3df083aSStefano Zampini     }
20159566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&ay));
2016a3df083aSStefano Zampini   }
2017a3df083aSStefano Zampini   PetscFunctionReturn(0);
2018a3df083aSStefano Zampini }
2019a3df083aSStefano Zampini 
2020a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
2021a3df083aSStefano Zampini {
2022a3df083aSStefano Zampini   PetscFunctionBegin;
20239566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE));
2024a3df083aSStefano Zampini   PetscFunctionReturn(0);
2025a3df083aSStefano Zampini }
2026a3df083aSStefano Zampini 
2027a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
2028a3df083aSStefano Zampini {
2029a3df083aSStefano Zampini   PetscFunctionBegin;
20309566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE));
2031a3df083aSStefano Zampini   PetscFunctionReturn(0);
2032a3df083aSStefano Zampini }
2033a3df083aSStefano Zampini 
2034a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
2035a3df083aSStefano Zampini {
2036a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
2037a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
2038a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
2039a3df083aSStefano Zampini 
2040a3df083aSStefano Zampini   PetscFunctionBegin;
2041a3df083aSStefano Zampini   if (!restore) {
20421dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
2043a3df083aSStefano Zampini     PetscScalar        *work;
2044b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
2045a3df083aSStefano Zampini 
204628b400f6SJacob Faibussowitsch     PetscCheck(!pcbddc->benign_original_mat,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
20479a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
20489566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n,&work));
20499566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF,&A_IB));
20509566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE));
20519566063dSJacob Faibussowitsch     PetscCall(MatSetType(A_IB,MATSHELL));
20529566063dSJacob Faibussowitsch     PetscCall(MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private));
20539566063dSJacob Faibussowitsch     PetscCall(MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private));
20549566063dSJacob Faibussowitsch     PetscCall(PetscNew(&ctx));
20559566063dSJacob Faibussowitsch     PetscCall(MatShellSetContext(A_IB,ctx));
2056a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
2057a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
2058a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
2059a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
2060059032f7SStefano Zampini     if (reuse) {
2061a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
20621dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
2063059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
2064059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
2065059032f7SStefano Zampini       PetscInt               i;
2066059032f7SStefano Zampini 
20679566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D));
20689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs));
2069059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20709566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]));
2071059032f7SStefano Zampini       }
20729566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&N_to_D));
20731dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2074059032f7SStefano Zampini     }
2075a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2076a3df083aSStefano Zampini     ctx->work = work;
20779566063dSJacob Faibussowitsch     PetscCall(MatSetUp(A_IB));
20789566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY));
20799566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY));
2080a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2081a3df083aSStefano Zampini 
2082a3df083aSStefano Zampini     /* A_BI as A_IB^T */
20839566063dSJacob Faibussowitsch     PetscCall(MatCreateTranspose(A_IB,&A_BI));
2084a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2085a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2086a3df083aSStefano Zampini   } else {
20871dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20881dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20891dd7afcfSStefano Zampini     }
20909566063dSJacob Faibussowitsch     PetscCall(MatShellGetContext(pcis->A_IB,&ctx));
20919566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
2092a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
20931dd7afcfSStefano Zampini     ctx->A = NULL;
20949566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
20951dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
20961dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
20971dd7afcfSStefano Zampini     if (ctx->free) {
2098059032f7SStefano Zampini       PetscInt i;
20991dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
21009566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&ctx->benign_zerodiag_subs[i]));
2101059032f7SStefano Zampini       }
21029566063dSJacob Faibussowitsch       PetscCall(PetscFree(ctx->benign_zerodiag_subs));
2103059032f7SStefano Zampini     }
21049566063dSJacob Faibussowitsch     PetscCall(PetscFree(ctx->work));
21059566063dSJacob Faibussowitsch     PetscCall(PetscFree(ctx));
2106a3df083aSStefano Zampini   }
2107a3df083aSStefano Zampini   PetscFunctionReturn(0);
2108a3df083aSStefano Zampini }
2109a3df083aSStefano Zampini 
2110a3df083aSStefano Zampini /* used just in bddc debug mode */
2111a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2112a3df083aSStefano Zampini {
2113a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2114a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2115a3df083aSStefano Zampini   Mat            An;
2116a3df083aSStefano Zampini 
2117a3df083aSStefano Zampini   PetscFunctionBegin;
21189566063dSJacob Faibussowitsch   PetscCall(MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An));
21199566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL));
2120a3df083aSStefano Zampini   if (is1) {
21219566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B));
21229566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&An));
2123a3df083aSStefano Zampini   } else {
2124a3df083aSStefano Zampini     *B = An;
2125a3df083aSStefano Zampini   }
2126a3df083aSStefano Zampini   PetscFunctionReturn(0);
2127a3df083aSStefano Zampini }
2128a3df083aSStefano Zampini 
21291cf9b237SStefano Zampini /* TODO: add reuse flag */
21301cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
21311cf9b237SStefano Zampini {
21321cf9b237SStefano Zampini   Mat            Bt;
21331cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
21341cf9b237SStefano Zampini   const PetscInt *ii,*ij;
21351cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
21361cf9b237SStefano Zampini   PetscBool      flg_row;
21371cf9b237SStefano Zampini 
21381cf9b237SStefano Zampini   PetscFunctionBegin;
21399566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&n,&m));
21409566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row));
21419566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&a));
21421cf9b237SStefano Zampini   nnz = n;
21431cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
21441cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
21451cf9b237SStefano Zampini   }
21469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n+1,&bii));
21479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&bij));
21489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&bdata));
21491cf9b237SStefano Zampini   nnz = 0;
21501cf9b237SStefano Zampini   bii[0] = 0;
21511cf9b237SStefano Zampini   for (i=0;i<n;i++) {
21521cf9b237SStefano Zampini     PetscInt j;
21531cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
21541cf9b237SStefano Zampini       PetscScalar entry = a[j];
21553272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
21561cf9b237SStefano Zampini         bij[nnz] = ij[j];
21571cf9b237SStefano Zampini         bdata[nnz] = entry;
21581cf9b237SStefano Zampini         nnz++;
21591cf9b237SStefano Zampini       }
21601cf9b237SStefano Zampini     }
21611cf9b237SStefano Zampini     bii[i+1] = nnz;
21621cf9b237SStefano Zampini   }
21639566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&a));
21649566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt));
21659566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row));
21661cf9b237SStefano Zampini   {
21671cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21681cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21691cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21701cf9b237SStefano Zampini   }
21713272d46bSStefano Zampini   if (*B == A) {
21729566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
21733272d46bSStefano Zampini   }
21741cf9b237SStefano Zampini   *B = Bt;
21751cf9b237SStefano Zampini   PetscFunctionReturn(0);
21761cf9b237SStefano Zampini }
21771cf9b237SStefano Zampini 
21788361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv)
21794f1b2e48SStefano Zampini {
2180c80a6c00SStefano Zampini   Mat                    B = NULL;
2181c80a6c00SStefano Zampini   DM                     dm;
21824f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21834f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21844f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2185c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21864f1b2e48SStefano Zampini   PetscInt               i,n;
21874f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2188c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21894f1b2e48SStefano Zampini 
21904f1b2e48SStefano Zampini   PetscFunctionBegin;
2191a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2192a2eca866SStefano Zampini   if (cc) *cc = NULL;
2193a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
21949566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&graph));
21959566063dSJacob Faibussowitsch   PetscCall(MatGetDM(pc->pmat,&dm));
21964f819b78SStefano Zampini   if (!dm) {
21979566063dSJacob Faibussowitsch     PetscCall(PCGetDM(pc,&dm));
2198c80a6c00SStefano Zampini   }
2199c80a6c00SStefano Zampini   if (dm) {
22009566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex));
2201c80a6c00SStefano Zampini   }
22028361f951SStefano Zampini   if (filter) isplex = PETSC_FALSE;
22038361f951SStefano Zampini 
2204c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2205c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2206c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2207c80a6c00SStefano Zampini     IS             cellNumbering;
2208c80a6c00SStefano Zampini     const PetscInt *cellNum;
2209c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2210c80a6c00SStefano Zampini     PetscSection   section;
2211c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2212c80a6c00SStefano Zampini     PetscSF        sfPoint;
2213c80a6c00SStefano Zampini 
22149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd));
22159566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
22169566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
2217c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
22189566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section));
22199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(section, pStart, pEnd));
22209566063dSJacob Faibussowitsch     PetscCall(PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer));
2221c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
22229566063dSJacob Faibussowitsch     PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure));
22239566063dSJacob Faibussowitsch     PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE));
22249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellNumbering(dm, &cellNumbering));
22259566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(cellNumbering, &cellNum));
2226c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2227c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2228c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2229c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
22309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
2231c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2232c80a6c00SStefano Zampini         const PetscInt point = adj[a];
22335cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2234c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
22359566063dSJacob Faibussowitsch           PetscCall(PetscSectionAddDof(section, p, 1));
22369566063dSJacob Faibussowitsch           PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf));
2237c80a6c00SStefano Zampini           *pBuf = point;
2238c80a6c00SStefano Zampini         }
2239c80a6c00SStefano Zampini       }
2240c80a6c00SStefano Zampini       n++;
2241c80a6c00SStefano Zampini     }
22429566063dSJacob Faibussowitsch     PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure));
2243c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
22449566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(section));
22459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(section, &size));
22469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n+1, &xadj));
2247c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2248c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
22499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, p, &(xadj[idx++])));
2250c80a6c00SStefano Zampini     }
2251c80a6c00SStefano Zampini     xadj[n] = size;
22529566063dSJacob Faibussowitsch     PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &adjncy));
2253c80a6c00SStefano Zampini     /* Clean up */
22549566063dSJacob Faibussowitsch     PetscCall(PetscSegBufferDestroy(&adjBuffer));
22559566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&section));
22569566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
2257c80a6c00SStefano Zampini     graph->xadj = xadj;
2258c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2259c80a6c00SStefano Zampini   } else {
2260c80a6c00SStefano Zampini     Mat       A;
22618361f951SStefano Zampini     PetscBool isseqaij, flg_row;
2262c80a6c00SStefano Zampini 
22639566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->pmat,&A));
226463c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
22659566063dSJacob Faibussowitsch       PetscCall(PCBDDCGraphDestroy(&graph));
226663c961adSStefano Zampini       PetscFunctionReturn(0);
226763c961adSStefano Zampini     }
22689566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij));
22694f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22701cf9b237SStefano Zampini       PetscBool isseqdense;
22711cf9b237SStefano Zampini 
22729566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense));
22731cf9b237SStefano Zampini       if (!isseqdense) {
22749566063dSJacob Faibussowitsch         PetscCall(MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B));
22751cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22761cf9b237SStefano Zampini         PetscScalar *array;
22771cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22781cf9b237SStefano Zampini 
22799566063dSJacob Faibussowitsch         PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&B));
22809566063dSJacob Faibussowitsch         PetscCall(MatDenseGetArray(B,&array));
22819566063dSJacob Faibussowitsch         PetscCall(MatGetSize(B,&n,NULL));
22821cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22831cf9b237SStefano Zampini           PetscInt j;
22841cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22851cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22861cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22871cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22881cf9b237SStefano Zampini           }
22891cf9b237SStefano Zampini         }
22909566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreArray(B,&array));
22919566063dSJacob Faibussowitsch         PetscCall(MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B));
22921cf9b237SStefano Zampini       }
22934f1b2e48SStefano Zampini     } else {
22949566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
22954f1b2e48SStefano Zampini       B = A;
22964f1b2e48SStefano Zampini     }
22979566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row));
22984f1b2e48SStefano Zampini 
22994f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
23004f1b2e48SStefano Zampini     if (filter) {
23014f1b2e48SStefano Zampini       PetscScalar *data;
23024f1b2e48SStefano Zampini       PetscInt    j,cum;
23034f1b2e48SStefano Zampini 
23049566063dSJacob Faibussowitsch       PetscCall(PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered));
23059566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(B,&data));
23064f1b2e48SStefano Zampini       cum = 0;
23074f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
23084f1b2e48SStefano Zampini         PetscInt t;
23094f1b2e48SStefano Zampini 
23104f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
23114f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
23124f1b2e48SStefano Zampini             continue;
23134f1b2e48SStefano Zampini           }
23144f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
23154f1b2e48SStefano Zampini         }
23164f1b2e48SStefano Zampini         t = xadj_filtered[i];
23174f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
23184f1b2e48SStefano Zampini         cum += t;
23194f1b2e48SStefano Zampini       }
23209566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(B,&data));
23214f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
23224f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
23234f1b2e48SStefano Zampini     } else {
23244f1b2e48SStefano Zampini       graph->xadj = xadj;
23254f1b2e48SStefano Zampini       graph->adjncy = adjncy;
23264f1b2e48SStefano Zampini     }
2327c80a6c00SStefano Zampini   }
2328c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
23299566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy));
23309566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy));
23319566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_dummy));
23329566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT));
23339566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap_dummy));
23349566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL));
23359566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphComputeConnectedComponents(graph));
2336c80a6c00SStefano Zampini 
23374f1b2e48SStefano Zampini   /* partial clean up */
23389566063dSJacob Faibussowitsch   PetscCall(PetscFree2(xadj_filtered,adjncy_filtered));
2339c80a6c00SStefano Zampini   if (B) {
2340c80a6c00SStefano Zampini     PetscBool flg_row;
23419566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row));
23429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
23434f1b2e48SStefano Zampini   }
2344c80a6c00SStefano Zampini   if (isplex) {
23459566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
23469566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
2347c80a6c00SStefano Zampini   }
23484f1b2e48SStefano Zampini 
23494f1b2e48SStefano Zampini   /* get back data */
2350c80a6c00SStefano Zampini   if (isplex) {
2351c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2352c80a6c00SStefano Zampini     if (cc || primalv) {
2353c80a6c00SStefano Zampini       Mat          A;
2354c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2355c80a6c00SStefano Zampini       PetscSection subSection;
2356c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2357c80a6c00SStefano Zampini 
23589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSubdomainSection(dm,&subSection));
23599566063dSJacob Faibussowitsch       PetscCall(MatISGetLocalMat(pc->pmat,&A));
23609566063dSJacob Faibussowitsch       PetscCall(PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids));
23619566063dSJacob Faibussowitsch       PetscCall(PetscBTCreate(A->rmap->n,&btv));
23629566063dSJacob Faibussowitsch       PetscCall(PetscBTCreate(A->rmap->n,&btvt));
2363c80a6c00SStefano Zampini 
2364c80a6c00SStefano Zampini       cids[0] = 0;
2365c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2366c80a6c00SStefano Zampini         PetscInt j;
2367c80a6c00SStefano Zampini 
23689566063dSJacob Faibussowitsch         PetscCall(PetscBTMemzero(A->rmap->n,btvt));
2369c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2370c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2371c80a6c00SStefano Zampini 
23729566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure));
2373c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
237420c3699dSStefano Zampini             PetscInt s, pp, p = closure[k], off, dof, cdof;
2375c80a6c00SStefano Zampini 
23769566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetConstraintDof(subSection,p,&cdof));
23779566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetOffset(subSection,p,&off));
23789566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetDof(subSection,p,&dof));
2379c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2380c80a6c00SStefano Zampini               if (PetscBTLookupSet(btvt,off+s)) continue;
2381e432b41dSStefano Zampini               if (!PetscBTLookup(btv,off+s)) ids[cum++] = off+s;
2382e432b41dSStefano Zampini               else pids[cump++] = off+s; /* cross-vertex */
2383c80a6c00SStefano Zampini             }
23849566063dSJacob Faibussowitsch             PetscCall(DMPlexGetTreeParent(dm,p,&pp,NULL));
238520c3699dSStefano Zampini             if (pp != p) {
23869566063dSJacob Faibussowitsch               PetscCall(PetscSectionGetConstraintDof(subSection,pp,&cdof));
23879566063dSJacob Faibussowitsch               PetscCall(PetscSectionGetOffset(subSection,pp,&off));
23889566063dSJacob Faibussowitsch               PetscCall(PetscSectionGetDof(subSection,pp,&dof));
238920c3699dSStefano Zampini               for (s = 0; s < dof-cdof; s++) {
239020c3699dSStefano Zampini                 if (PetscBTLookupSet(btvt,off+s)) continue;
2391e432b41dSStefano Zampini                 if (!PetscBTLookup(btv,off+s)) ids[cum++] = off+s;
2392e432b41dSStefano Zampini                 else pids[cump++] = off+s; /* cross-vertex */
239320c3699dSStefano Zampini               }
239420c3699dSStefano Zampini             }
2395c80a6c00SStefano Zampini           }
23969566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure));
2397c80a6c00SStefano Zampini         }
2398c80a6c00SStefano Zampini         cids[i+1] = cum;
2399c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2400c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
24019566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(btv,ids[j]));
2402c80a6c00SStefano Zampini         }
2403c80a6c00SStefano Zampini       }
2404c80a6c00SStefano Zampini       if (cc) {
24059566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(graph->ncc,&cc_n));
2406c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
24079566063dSJacob Faibussowitsch           PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]));
2408c80a6c00SStefano Zampini         }
2409c80a6c00SStefano Zampini         *cc = cc_n;
2410c80a6c00SStefano Zampini       }
24111baa6e33SBarry Smith       if (primalv) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv));
24129566063dSJacob Faibussowitsch       PetscCall(PetscFree3(ids,cids,pids));
24139566063dSJacob Faibussowitsch       PetscCall(PetscBTDestroy(&btv));
24149566063dSJacob Faibussowitsch       PetscCall(PetscBTDestroy(&btvt));
2415c80a6c00SStefano Zampini     }
2416c80a6c00SStefano Zampini   } else {
24171cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
24181cf9b237SStefano Zampini     if (cc) {
24199566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(graph->ncc,&cc_n));
24204f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
24219566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,graph->cptr[i+1]-graph->cptr[i],graph->queue+graph->cptr[i],PETSC_COPY_VALUES,&cc_n[i]));
24224f1b2e48SStefano Zampini       }
24234f1b2e48SStefano Zampini       *cc = cc_n;
24241cf9b237SStefano Zampini     }
2425c80a6c00SStefano Zampini   }
24264f1b2e48SStefano Zampini   /* clean up graph */
24270a545947SLisandro Dalcin   graph->xadj = NULL;
24280a545947SLisandro Dalcin   graph->adjncy = NULL;
24299566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphDestroy(&graph));
24304f1b2e48SStefano Zampini   PetscFunctionReturn(0);
24314f1b2e48SStefano Zampini }
24324f1b2e48SStefano Zampini 
24335408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
24345408967cSStefano Zampini {
24355408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24365408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2437dee84bffSStefano Zampini   IS             dirIS = NULL;
24384f1b2e48SStefano Zampini   PetscInt       i;
24395408967cSStefano Zampini 
24405408967cSStefano Zampini   PetscFunctionBegin;
24419566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS));
24425408967cSStefano Zampini   if (zerodiag) {
24435408967cSStefano Zampini     Mat            A;
24445408967cSStefano Zampini     Vec            vec3_N;
24455408967cSStefano Zampini     PetscScalar    *vals;
24465408967cSStefano Zampini     const PetscInt *idxs;
2447d12d3064SStefano Zampini     PetscInt       nz,*count;
24485408967cSStefano Zampini 
24495408967cSStefano Zampini     /* p0 */
24509566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_N,0.));
24519566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n,&vals));
24529566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(zerodiag,&nz));
24539566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(zerodiag,&idxs));
24544f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
24559566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES));
24569566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec1_N));
24579566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec1_N));
24585408967cSStefano Zampini     /* v_I */
24599566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(pcis->vec2_N,NULL));
24605408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
24619566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES));
24629566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(zerodiag,&idxs));
24639566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcis->is_B_local,&idxs));
24645408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24659566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES));
24669566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcis->is_B_local,&idxs));
24675408967cSStefano Zampini     if (dirIS) {
24685408967cSStefano Zampini       PetscInt n;
24695408967cSStefano Zampini 
24709566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS,&n));
24719566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS,&idxs));
24725408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24739566063dSJacob Faibussowitsch       PetscCall(VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES));
24749566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS,&idxs));
24755408967cSStefano Zampini     }
24769566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec2_N));
24779566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec2_N));
24789566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_N,&vec3_N));
24799566063dSJacob Faibussowitsch     PetscCall(VecSet(vec3_N,0.));
24809566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->pmat,&A));
24819566063dSJacob Faibussowitsch     PetscCall(MatMult(A,pcis->vec1_N,vec3_N));
24829566063dSJacob Faibussowitsch     PetscCall(VecDot(vec3_N,pcis->vec2_N,&vals[0]));
24837827d75bSBarry Smith     PetscCheck(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.)",(double)PetscAbsScalar(vals[0]));
24849566063dSJacob Faibussowitsch     PetscCall(PetscFree(vals));
24859566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vec3_N));
2486d12d3064SStefano Zampini 
2487d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
24889566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(pcis->n,&count));
24899566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcis->is_B_local,&idxs));
2490d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
24919566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcis->is_B_local,&idxs));
24929566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(zerodiag,&idxs));
249363a3b9bcSJacob Faibussowitsch     for (i=0;i<nz;i++) PetscCheck(!count[idxs[i]],PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %" PetscInt_FMT " is an interface dof",idxs[i]);
24949566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(zerodiag,&idxs));
24959566063dSJacob Faibussowitsch     PetscCall(PetscFree(count));
24965408967cSStefano Zampini   }
24979566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&dirIS));
24985408967cSStefano Zampini 
24995408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
25009566063dSJacob Faibussowitsch   PetscCall(VecSetRandom(pcis->vec1_global,NULL));
25014f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
25029566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE));
25034f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
25049566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE));
2505f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2506f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
250763a3b9bcSJacob Faibussowitsch     PetscCheck(val == -PetscGlobalRank-i,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %g at %" PetscInt_FMT " instead of %g",(double)PetscRealPart(pcbddc->benign_p0[i]),i,(double)(-PetscGlobalRank-i));
2508f2a566d8SStefano Zampini   }
25095408967cSStefano Zampini   PetscFunctionReturn(0);
25105408967cSStefano Zampini }
25115408967cSStefano Zampini 
25123b03f7bbSStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal)
2513339f8db1SStefano Zampini {
2514339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2515e432b41dSStefano Zampini   Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
25163b03f7bbSStefano Zampini   IS             pressures = NULL,zerodiag = NULL,*bzerodiag = NULL,zerodiag_save,*zerodiag_subs;
25173b03f7bbSStefano Zampini   PetscInt       nz,n,benign_n,bsp = 1;
25184edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
25194edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2520339f8db1SStefano Zampini 
2521339f8db1SStefano Zampini   PetscFunctionBegin;
25223b03f7bbSStefano Zampini   if (reuse) goto project_b0;
25239566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&pcbddc->benign_sf));
25249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->benign_B0));
2525a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
25269566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[n]));
2527a3df083aSStefano Zampini   }
25289566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->benign_zerodiag_subs));
25293b03f7bbSStefano Zampini   has_null_pressures = PETSC_TRUE;
25303b03f7bbSStefano Zampini   have_null = PETSC_TRUE;
25313b03f7bbSStefano Zampini   /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided)
25323b03f7bbSStefano Zampini      Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field)
25334f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
25344f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
25351ae86dd6SStefano Zampini      since the local Schur complements are already SPD
25364f1b2e48SStefano Zampini   */
253740fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
25387fbe2174Sstefano_zampini     IS        iP = NULL;
25393b03f7bbSStefano Zampini     PetscInt  p,*pp;
25403b03f7bbSStefano Zampini     PetscBool flg;
25414f1b2e48SStefano Zampini 
25429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal,&pp));
25433b03f7bbSStefano Zampini     n    = pcbddc->n_ISForDofsLocal;
2544d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");
25459566063dSJacob Faibussowitsch     PetscCall(PetscOptionsIntArray("-pc_bddc_pressure_field","Field id for pressures",NULL,pp,&n,&flg));
2546d0609cedSBarry Smith     PetscOptionsEnd();
25473b03f7bbSStefano Zampini     if (!flg) {
25483b03f7bbSStefano Zampini       n = 1;
25493b03f7bbSStefano Zampini       pp[0] = pcbddc->n_ISForDofsLocal-1;
25503b03f7bbSStefano Zampini     }
25513b03f7bbSStefano Zampini 
25523b03f7bbSStefano Zampini     bsp = 0;
25533b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25543b03f7bbSStefano Zampini       PetscInt bs;
25553b03f7bbSStefano Zampini 
255663a3b9bcSJacob Faibussowitsch       PetscCheck(pp[p] >= 0 && pp[p] < pcbddc->n_ISForDofsLocal,PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %" PetscInt_FMT,pp[p]);
25579566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs));
25583b03f7bbSStefano Zampini       bsp += bs;
25593b03f7bbSStefano Zampini     }
25609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bsp,&bzerodiag));
25613b03f7bbSStefano Zampini     bsp  = 0;
25623b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25633b03f7bbSStefano Zampini       const PetscInt *idxs;
25643b03f7bbSStefano Zampini       PetscInt       b,bs,npl,*bidxs;
25653b03f7bbSStefano Zampini 
25669566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs));
25679566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]],&npl));
25689566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs));
25699566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(npl/bs,&bidxs));
25703b03f7bbSStefano Zampini       for (b=0;b<bs;b++) {
25713b03f7bbSStefano Zampini         PetscInt i;
25723b03f7bbSStefano Zampini 
25733b03f7bbSStefano Zampini         for (i=0;i<npl/bs;i++) bidxs[i] = idxs[bs*i+b];
25749566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,npl/bs,bidxs,PETSC_COPY_VALUES,&bzerodiag[bsp]));
25753b03f7bbSStefano Zampini         bsp++;
25763b03f7bbSStefano Zampini       }
25779566063dSJacob Faibussowitsch       PetscCall(PetscFree(bidxs));
25789566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs));
25793b03f7bbSStefano Zampini     }
25809566063dSJacob Faibussowitsch     PetscCall(ISConcatenate(PETSC_COMM_SELF,bsp,bzerodiag,&pressures));
25813b03f7bbSStefano Zampini 
25827fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
25839566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP));
25847fbe2174Sstefano_zampini     if (iP) {
25857fbe2174Sstefano_zampini       IS newpressures;
25867fbe2174Sstefano_zampini 
25879566063dSJacob Faibussowitsch       PetscCall(ISDifference(pressures,iP,&newpressures));
25889566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pressures));
25897fbe2174Sstefano_zampini       pressures = newpressures;
25907fbe2174Sstefano_zampini     }
25919566063dSJacob Faibussowitsch     PetscCall(ISSorted(pressures,&sorted));
259240fa8d13SStefano Zampini     if (!sorted) {
25939566063dSJacob Faibussowitsch       PetscCall(ISSort(pressures));
259440fa8d13SStefano Zampini     }
25959566063dSJacob Faibussowitsch     PetscCall(PetscFree(pp));
259640fa8d13SStefano Zampini   }
25973b03f7bbSStefano Zampini 
259897d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
25999566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(pcbddc->local_mat,&n,NULL));
260027b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
26019566063dSJacob Faibussowitsch   PetscCall(MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag));
26029566063dSJacob Faibussowitsch   PetscCall(ISSorted(zerodiag,&sorted));
2603339f8db1SStefano Zampini   if (!sorted) {
26049566063dSJacob Faibussowitsch     PetscCall(ISSort(zerodiag));
2605339f8db1SStefano Zampini   }
26069566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)zerodiag));
26074edc6404Sstefano_zampini   zerodiag_save = zerodiag;
26089566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(zerodiag,&nz));
26094f1b2e48SStefano Zampini   if (!nz) {
26104f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
26114f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
26129566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&zerodiag));
261340fa8d13SStefano Zampini   }
26144f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
26153b03f7bbSStefano Zampini 
26164f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
26174f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
26183b03f7bbSStefano Zampini   benign_n         = 0;
26191f4df5f7SStefano Zampini   n_interior_dofs  = 0;
26201f4df5f7SStefano Zampini   interior_dofs    = NULL;
26214edc6404Sstefano_zampini   nneu             = 0;
26224edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
26239566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu));
26244edc6404Sstefano_zampini   }
26253369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
26264edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
26271f4df5f7SStefano Zampini     PetscInt n,i,j;
26281f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
26291f4df5f7SStefano Zampini     PetscInt *iwork;
26301f4df5f7SStefano Zampini 
26319566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&n));
26329566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetInfo(matis->rmapping,&n_neigh,&neigh,&n_shared,&shared));
26339566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n,&iwork));
26349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&interior_dofs));
263590648384SStefano Zampini     for (i=1;i<n_neigh;i++)
26361f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
26371f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
26381f4df5f7SStefano Zampini     for (i=0;i<n;i++)
26391f4df5f7SStefano Zampini       if (!iwork[i])
26401f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
26419566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
26429566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreInfo(matis->rmapping,&n_neigh,&neigh,&n_shared,&shared));
26431f4df5f7SStefano Zampini   }
26444f1b2e48SStefano Zampini   if (has_null_pressures) {
26454f1b2e48SStefano Zampini     IS             *subs;
26464edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
26471f4df5f7SStefano Zampini     const PetscInt *idxs;
26481f4df5f7SStefano Zampini     PetscScalar    *array;
26491f4df5f7SStefano Zampini     Vec            *work;
26504f1b2e48SStefano Zampini 
26514f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
26524f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
26531f4df5f7SStefano 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) */
26544edc6404Sstefano_zampini     if (checkb) {
26559566063dSJacob Faibussowitsch       PetscCall(VecDuplicateVecs(matis->y,2,&work));
26569566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(zerodiag,&nl));
26579566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(zerodiag,&idxs));
26581f4df5f7SStefano Zampini       /* work[0] = 1_p */
26599566063dSJacob Faibussowitsch       PetscCall(VecSet(work[0],0.));
26609566063dSJacob Faibussowitsch       PetscCall(VecGetArray(work[0],&array));
26611f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26629566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(work[0],&array));
26631f4df5f7SStefano Zampini       /* work[0] = 1_v */
26649566063dSJacob Faibussowitsch       PetscCall(VecSet(work[1],1.));
26659566063dSJacob Faibussowitsch       PetscCall(VecGetArray(work[1],&array));
26661f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
26679566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(work[1],&array));
26689566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(zerodiag,&idxs));
26691f4df5f7SStefano Zampini     }
26703b03f7bbSStefano Zampini 
26713b03f7bbSStefano Zampini     if (nsubs > 1 || bsp > 1) {
26723b03f7bbSStefano Zampini       IS       *is;
26733b03f7bbSStefano Zampini       PetscInt b,totb;
26743b03f7bbSStefano Zampini 
26753b03f7bbSStefano Zampini       totb  = bsp;
26763b03f7bbSStefano Zampini       is    = bsp > 1 ? bzerodiag : &zerodiag;
26773b03f7bbSStefano Zampini       nsubs = PetscMax(nsubs,1);
26789566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nsubs*totb,&zerodiag_subs));
26793b03f7bbSStefano Zampini       for (b=0;b<totb;b++) {
26804f1b2e48SStefano Zampini         for (i=0;i<nsubs;i++) {
26814f1b2e48SStefano Zampini           ISLocalToGlobalMapping l2g;
26824f1b2e48SStefano Zampini           IS                     t_zerodiag_subs;
26834f1b2e48SStefano Zampini           PetscInt               nl;
26844f1b2e48SStefano Zampini 
26853b03f7bbSStefano Zampini           if (subs) {
26869566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingCreateIS(subs[i],&l2g));
26873b03f7bbSStefano Zampini           } else {
26883b03f7bbSStefano Zampini             IS tis;
26893b03f7bbSStefano Zampini 
26909566063dSJacob Faibussowitsch             PetscCall(MatGetLocalSize(pcbddc->local_mat,&nl,NULL));
26919566063dSJacob Faibussowitsch             PetscCall(ISCreateStride(PETSC_COMM_SELF,nl,0,1,&tis));
26929566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingCreateIS(tis,&l2g));
26939566063dSJacob Faibussowitsch             PetscCall(ISDestroy(&tis));
26943b03f7bbSStefano Zampini           }
26959566063dSJacob Faibussowitsch           PetscCall(ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,is[b],&t_zerodiag_subs));
26969566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(t_zerodiag_subs,&nl));
26974f1b2e48SStefano Zampini           if (nl) {
26984f1b2e48SStefano Zampini             PetscBool valid = PETSC_TRUE;
26994f1b2e48SStefano Zampini 
27004edc6404Sstefano_zampini             if (checkb) {
27019566063dSJacob Faibussowitsch               PetscCall(VecSet(matis->x,0));
27029566063dSJacob Faibussowitsch               PetscCall(ISGetLocalSize(subs[i],&nl));
27039566063dSJacob Faibussowitsch               PetscCall(ISGetIndices(subs[i],&idxs));
27049566063dSJacob Faibussowitsch               PetscCall(VecGetArray(matis->x,&array));
27051f4df5f7SStefano Zampini               for (j=0;j<nl;j++) array[idxs[j]] = 1.;
27069566063dSJacob Faibussowitsch               PetscCall(VecRestoreArray(matis->x,&array));
27079566063dSJacob Faibussowitsch               PetscCall(ISRestoreIndices(subs[i],&idxs));
27089566063dSJacob Faibussowitsch               PetscCall(VecPointwiseMult(matis->x,work[0],matis->x));
27099566063dSJacob Faibussowitsch               PetscCall(MatMult(matis->A,matis->x,matis->y));
27109566063dSJacob Faibussowitsch               PetscCall(VecPointwiseMult(matis->y,work[1],matis->y));
27119566063dSJacob Faibussowitsch               PetscCall(VecGetArray(matis->y,&array));
27121f4df5f7SStefano Zampini               for (j=0;j<n_interior_dofs;j++) {
27131f4df5f7SStefano Zampini                 if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27141f4df5f7SStefano Zampini                   valid = PETSC_FALSE;
27151f4df5f7SStefano Zampini                   break;
27161f4df5f7SStefano Zampini                 }
27171f4df5f7SStefano Zampini               }
27189566063dSJacob Faibussowitsch               PetscCall(VecRestoreArray(matis->y,&array));
27191f4df5f7SStefano Zampini             }
27206632bad2Sstefano_zampini             if (valid && nneu) {
27216632bad2Sstefano_zampini               const PetscInt *idxs;
27221f4df5f7SStefano Zampini               PetscInt       nzb;
27231f4df5f7SStefano Zampini 
27249566063dSJacob Faibussowitsch               PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs));
27259566063dSJacob Faibussowitsch               PetscCall(ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL));
27269566063dSJacob Faibussowitsch               PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs));
27271f4df5f7SStefano Zampini               if (nzb) valid = PETSC_FALSE;
27281f4df5f7SStefano Zampini             }
27291f4df5f7SStefano Zampini             if (valid && pressures) {
27303b03f7bbSStefano Zampini               IS       t_pressure_subs,tmp;
27313b03f7bbSStefano Zampini               PetscInt i1,i2;
27323b03f7bbSStefano Zampini 
27339566063dSJacob Faibussowitsch               PetscCall(ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs));
27349566063dSJacob Faibussowitsch               PetscCall(ISEmbed(t_zerodiag_subs,t_pressure_subs,PETSC_TRUE,&tmp));
27359566063dSJacob Faibussowitsch               PetscCall(ISGetLocalSize(tmp,&i1));
27369566063dSJacob Faibussowitsch               PetscCall(ISGetLocalSize(t_zerodiag_subs,&i2));
27373b03f7bbSStefano Zampini               if (i2 != i1) valid = PETSC_FALSE;
27389566063dSJacob Faibussowitsch               PetscCall(ISDestroy(&t_pressure_subs));
27399566063dSJacob Faibussowitsch               PetscCall(ISDestroy(&tmp));
27404f1b2e48SStefano Zampini             }
27414f1b2e48SStefano Zampini             if (valid) {
27429566063dSJacob Faibussowitsch               PetscCall(ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[benign_n]));
27433b03f7bbSStefano Zampini               benign_n++;
27443b03f7bbSStefano Zampini             } else recompute_zerodiag = PETSC_TRUE;
27454f1b2e48SStefano Zampini           }
27469566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&t_zerodiag_subs));
27479566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingDestroy(&l2g));
27484f1b2e48SStefano Zampini         }
27493b03f7bbSStefano Zampini       }
27504f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
27514f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
27521f4df5f7SStefano Zampini 
27536632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
27541f4df5f7SStefano Zampini       if (valid && pressures) {
27559566063dSJacob Faibussowitsch         PetscCall(ISEqual(pressures,zerodiag,&valid));
27564f1b2e48SStefano Zampini       }
27574edc6404Sstefano_zampini       if (valid && checkb) {
27589566063dSJacob Faibussowitsch         PetscCall(MatMult(matis->A,work[0],matis->x));
27599566063dSJacob Faibussowitsch         PetscCall(VecPointwiseMult(matis->x,work[1],matis->x));
27609566063dSJacob Faibussowitsch         PetscCall(VecGetArray(matis->x,&array));
27611f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
27621f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27631f4df5f7SStefano Zampini             valid = PETSC_FALSE;
27641f4df5f7SStefano Zampini             break;
27651f4df5f7SStefano Zampini           }
27661f4df5f7SStefano Zampini         }
27679566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(matis->x,&array));
27681f4df5f7SStefano Zampini       }
27694f1b2e48SStefano Zampini       if (valid) {
27703b03f7bbSStefano Zampini         benign_n = 1;
27719566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(benign_n,&zerodiag_subs));
27729566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)zerodiag));
27734f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
27744f1b2e48SStefano Zampini       }
27754f1b2e48SStefano Zampini     }
27764edc6404Sstefano_zampini     if (checkb) {
27779566063dSJacob Faibussowitsch       PetscCall(VecDestroyVecs(2,&work));
27784f1b2e48SStefano Zampini     }
27791f4df5f7SStefano Zampini   }
27809566063dSJacob Faibussowitsch   PetscCall(PetscFree(interior_dofs));
27814f1b2e48SStefano Zampini 
27823b03f7bbSStefano Zampini   if (!benign_n) {
2783b9b0e38cSStefano Zampini     PetscInt n;
2784b9b0e38cSStefano Zampini 
27859566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&zerodiag));
27864f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
27879566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pcbddc->local_mat,&n,NULL));
278876a58201SStefano Zampini     if (n) have_null = PETSC_FALSE;
2789b9b0e38cSStefano Zampini   }
27904f1b2e48SStefano Zampini 
27914f1b2e48SStefano Zampini   /* final check for null pressures */
27924f1b2e48SStefano Zampini   if (zerodiag && pressures) {
27939566063dSJacob Faibussowitsch     PetscCall(ISEqual(pressures,zerodiag,&have_null));
27944f1b2e48SStefano Zampini   }
27954f1b2e48SStefano Zampini 
27964f1b2e48SStefano Zampini   if (recompute_zerodiag) {
27979566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&zerodiag));
27983b03f7bbSStefano Zampini     if (benign_n == 1) {
27999566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)zerodiag_subs[0]));
28004f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
28014f1b2e48SStefano Zampini     } else {
28024f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
28034f1b2e48SStefano Zampini 
28044f1b2e48SStefano Zampini       nzn = 0;
28053b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28064f1b2e48SStefano Zampini         PetscInt ns;
28079566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(zerodiag_subs[i],&ns));
28084f1b2e48SStefano Zampini         nzn += ns;
28094f1b2e48SStefano Zampini       }
28109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nzn,&new_idxs));
28114f1b2e48SStefano Zampini       nzn = 0;
28123b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28134f1b2e48SStefano Zampini         PetscInt ns,*idxs;
28149566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(zerodiag_subs[i],&ns));
28159566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs));
28169566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(new_idxs+nzn,idxs,ns));
28179566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs));
28184f1b2e48SStefano Zampini         nzn += ns;
28194f1b2e48SStefano Zampini       }
28209566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(nzn,new_idxs));
28219566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag));
28224f1b2e48SStefano Zampini     }
28234f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
28244f1b2e48SStefano Zampini   }
28254f1b2e48SStefano Zampini 
28263b03f7bbSStefano Zampini   /* determines if the coarse solver will be singular or not */
28271c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc)));
28283b03f7bbSStefano Zampini 
2829669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2830a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2831a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2832a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2833a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2834a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2835a198735bSStefano Zampini 
28361f4df5f7SStefano Zampini     if (pressures) {
28371f4df5f7SStefano Zampini       isused = pressures;
28381f4df5f7SStefano Zampini     } else {
28394edc6404Sstefano_zampini       isused = zerodiag_save;
28401f4df5f7SStefano Zampini     }
28419566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL));
28429566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->pmat,&A));
28439566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A,&n,NULL));
28447827d75bSBarry Smith     PetscCheck(isused || (n == 0),PETSC_COMM_SELF,PETSC_ERR_USER,"Don't know how to extract div u dot p! Please provide the pressure field");
2845a198735bSStefano Zampini     n_isused = 0;
2846a198735bSStefano Zampini     if (isused) {
28479566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(isused,&n_isused));
2848a198735bSStefano Zampini     }
28499566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc)));
2850a198735bSStefano Zampini     st = st-n_isused;
28511ae86dd6SStefano Zampini     if (n) {
2852a198735bSStefano Zampini       const PetscInt *gidxs;
2853a198735bSStefano Zampini 
28549566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp));
28559566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs));
2856a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
28579566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row));
28589566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col));
28599566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs));
28601ae86dd6SStefano Zampini     } else {
28619566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp));
28629566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row));
28639566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col));
2864a198735bSStefano Zampini     }
28659566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->pmat,NULL,&N));
28669566063dSJacob Faibussowitsch     PetscCall(ISGetSize(row,&M));
28679566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(row,&rl2g));
28689566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(col,&cl2g));
28699566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&row));
28709566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&col));
28719566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp));
28729566063dSJacob Faibussowitsch     PetscCall(MatSetType(pcbddc->divudotp,MATIS));
28739566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N));
28749566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g));
28759566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
28769566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
28779566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(pcbddc->divudotp,loc_divudotp));
28789566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&loc_divudotp));
28799566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY));
28809566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY));
28811ae86dd6SStefano Zampini   }
28829566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag_save));
28839566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pressures));
28843b03f7bbSStefano Zampini   if (bzerodiag) {
28853b03f7bbSStefano Zampini     PetscInt i;
2886b3afcdbeSStefano Zampini 
28873b03f7bbSStefano Zampini     for (i=0;i<bsp;i++) {
28889566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&bzerodiag[i]));
28893b03f7bbSStefano Zampini     }
28909566063dSJacob Faibussowitsch     PetscCall(PetscFree(bzerodiag));
28913b03f7bbSStefano Zampini   }
28923b03f7bbSStefano Zampini   pcbddc->benign_n = benign_n;
28933b03f7bbSStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
28943b03f7bbSStefano Zampini 
28953b03f7bbSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
28963b03f7bbSStefano Zampini   have_null = (PetscBool)(!!pcbddc->benign_n);
28971c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
28983b03f7bbSStefano Zampini 
28993b03f7bbSStefano Zampini project_b0:
29009566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(pcbddc->local_mat,&n,NULL));
2901b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
29023b03f7bbSStefano Zampini   if (pcbddc->benign_n) {
29034f1b2e48SStefano Zampini     PetscInt i,s,*nnz;
29044f1b2e48SStefano Zampini 
2905339f8db1SStefano Zampini     /* local change of basis for pressures */
29069566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->benign_change));
29079566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change));
29089566063dSJacob Faibussowitsch     PetscCall(MatSetType(pcbddc->benign_change,MATAIJ));
29099566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE));
29109566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&nnz));
2911aa0d93e9SStefano Zampini     for (i=0;i<n;i++) nnz[i] = 1; /* defaults to identity */
29124f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2913aa0d93e9SStefano Zampini       const PetscInt *idxs;
29144f1b2e48SStefano Zampini       PetscInt       nzs,j;
29154f1b2e48SStefano Zampini 
29169566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nzs));
29179566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i],&idxs));
29184f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
29194f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
29209566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],&idxs));
29214f1b2e48SStefano Zampini     }
29229566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz));
29239566063dSJacob Faibussowitsch     PetscCall(MatSetOption(pcbddc->benign_change,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
29249566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
2925aa0d93e9SStefano Zampini     /* set identity by default */
2926aa0d93e9SStefano Zampini     for (i=0;i<n;i++) {
29279566063dSJacob Faibussowitsch       PetscCall(MatSetValue(pcbddc->benign_change,i,i,1.,INSERT_VALUES));
2928339f8db1SStefano Zampini     }
29299566063dSJacob Faibussowitsch     PetscCall(PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0));
29309566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(pcbddc->benign_n,&pcbddc->benign_p0_lidx,pcbddc->benign_n,&pcbddc->benign_p0_gidx,pcbddc->benign_n,&pcbddc->benign_p0));
2931339f8db1SStefano Zampini     /* set change on pressures */
29324f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
29334f1b2e48SStefano Zampini       PetscScalar    *array;
2934aa0d93e9SStefano Zampini       const PetscInt *idxs;
29354f1b2e48SStefano Zampini       PetscInt       nzs;
29364f1b2e48SStefano Zampini 
29379566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[s],&nzs));
29389566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[s],&idxs));
29394f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2940339f8db1SStefano Zampini         PetscScalar vals[2];
2941339f8db1SStefano Zampini         PetscInt    cols[2];
2942339f8db1SStefano Zampini 
2943339f8db1SStefano Zampini         cols[0] = idxs[i];
29444f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2945339f8db1SStefano Zampini         vals[0] = 1.;
2946b0f5fe93SStefano Zampini         vals[1] = 1.;
29479566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES));
2948339f8db1SStefano Zampini       }
29499566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nzs,&array));
29504f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
29514f1b2e48SStefano Zampini       array[nzs-1] = 1.;
29529566063dSJacob Faibussowitsch       PetscCall(MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES));
29534f1b2e48SStefano Zampini       /* store local idxs for p0 */
29544f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
29559566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[s],&idxs));
29569566063dSJacob Faibussowitsch       PetscCall(PetscFree(array));
29574f1b2e48SStefano Zampini     }
29589566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY));
29599566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY));
29603b03f7bbSStefano Zampini 
2961a3df083aSStefano Zampini     /* project if needed */
2962a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29631dd7afcfSStefano Zampini       Mat M;
29641dd7afcfSStefano Zampini 
29659566063dSJacob Faibussowitsch       PetscCall(MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M));
29669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->local_mat));
29679566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCompress(M,&pcbddc->local_mat));
29689566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M));
2969a3df083aSStefano Zampini     }
29704f1b2e48SStefano Zampini     /* store global idxs for p0 */
29719566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(matis->rmapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx));
2972339f8db1SStefano Zampini   }
2973339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2974339f8db1SStefano Zampini   PetscFunctionReturn(0);
2975339f8db1SStefano Zampini }
2976339f8db1SStefano Zampini 
2977015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2978efc2fbd9SStefano Zampini {
2979efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2980de9d7bd0SStefano Zampini   PetscScalar    *array;
2981efc2fbd9SStefano Zampini 
2982efc2fbd9SStefano Zampini   PetscFunctionBegin;
2983efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
29849566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf));
29859566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx));
2986efc2fbd9SStefano Zampini   }
2987de9d7bd0SStefano Zampini   if (get) {
29889566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(v,(const PetscScalar**)&array));
29899566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0,MPI_REPLACE));
29909566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0,MPI_REPLACE));
29919566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(v,(const PetscScalar**)&array));
2992de9d7bd0SStefano Zampini   } else {
29939566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v,&array));
29949566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPI_REPLACE));
29959566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPI_REPLACE));
29969566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v,&array));
2997efc2fbd9SStefano Zampini   }
2998efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2999efc2fbd9SStefano Zampini }
3000efc2fbd9SStefano Zampini 
3001c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
3002c263805aSStefano Zampini {
3003c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3004c263805aSStefano Zampini 
3005c263805aSStefano Zampini   PetscFunctionBegin;
3006c263805aSStefano Zampini   /* TODO: add error checking
3007c263805aSStefano Zampini     - avoid nested pop (or push) calls.
3008c263805aSStefano Zampini     - cannot push before pop.
30091c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
3010c263805aSStefano Zampini   */
30114f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
3012efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
3013efc2fbd9SStefano Zampini   }
3014c263805aSStefano Zampini   if (pop) {
3015a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
30164f1b2e48SStefano Zampini       IS       is_p0;
30174f1b2e48SStefano Zampini       MatReuse reuse;
3018c263805aSStefano Zampini 
3019c263805aSStefano Zampini       /* extract B_0 */
30204f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
30214f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
30224f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
30234f1b2e48SStefano Zampini       }
30249566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0));
30259566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0));
3026c263805aSStefano Zampini       /* remove rows and cols from local problem */
30279566063dSJacob Faibussowitsch       PetscCall(MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE));
30289566063dSJacob Faibussowitsch       PetscCall(MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE));
30299566063dSJacob Faibussowitsch       PetscCall(MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL));
30309566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is_p0));
3031a3df083aSStefano Zampini     } else {
3032a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
3033a3df083aSStefano Zampini       PetscScalar *vals;
3034a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
3035a3df083aSStefano Zampini 
30369566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(matis->y,&n));
30379566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(n,&idxs_ins,n,&vals));
3038a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
30390b5adadeSStefano Zampini         PetscInt *nnz;
30409566063dSJacob Faibussowitsch         PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0));
30419566063dSJacob Faibussowitsch         PetscCall(MatSetType(pcbddc->benign_B0,MATAIJ));
30429566063dSJacob Faibussowitsch         PetscCall(MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE));
30439566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(pcbddc->benign_n,&nnz));
3044331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
30459566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]));
3046331e053bSStefano Zampini           nnz[i] = n - nnz[i];
3047331e053bSStefano Zampini         }
30489566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz));
30499566063dSJacob Faibussowitsch         PetscCall(MatSetOption(pcbddc->benign_B0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
30509566063dSJacob Faibussowitsch         PetscCall(PetscFree(nnz));
3051331e053bSStefano Zampini       }
3052a3df083aSStefano Zampini 
3053a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3054a3df083aSStefano Zampini         PetscScalar *array;
3055a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
3056a3df083aSStefano Zampini 
30579566063dSJacob Faibussowitsch         PetscCall(VecSet(matis->x,0.));
30589566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz));
30599566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs));
3060a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
30619566063dSJacob Faibussowitsch         PetscCall(VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES));
30629566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(matis->x));
30639566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(matis->x));
30649566063dSJacob Faibussowitsch         PetscCall(VecSet(matis->y,0.));
30659566063dSJacob Faibussowitsch         PetscCall(MatMult(matis->A,matis->x,matis->y));
30669566063dSJacob Faibussowitsch         PetscCall(VecGetArray(matis->y,&array));
3067a3df083aSStefano Zampini         cum = 0;
3068a3df083aSStefano Zampini         for (j=0;j<n;j++) {
306922db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
3070a3df083aSStefano Zampini             vals[cum] = array[j];
3071a3df083aSStefano Zampini             idxs_ins[cum] = j;
3072a3df083aSStefano Zampini             cum++;
3073a3df083aSStefano Zampini           }
3074a3df083aSStefano Zampini         }
30759566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES));
30769566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(matis->y,&array));
30779566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs));
3078a3df083aSStefano Zampini       }
30799566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY));
30809566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY));
30819566063dSJacob Faibussowitsch       PetscCall(PetscFree2(idxs_ins,vals));
3082a3df083aSStefano Zampini     }
3083c263805aSStefano Zampini   } else { /* push */
3084a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
30854f1b2e48SStefano Zampini       PetscInt i;
30864f1b2e48SStefano Zampini 
30874f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
30884f1b2e48SStefano Zampini         PetscScalar *B0_vals;
30894f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
30904f1b2e48SStefano Zampini 
30919566063dSJacob Faibussowitsch         PetscCall(MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals));
30929566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES));
30939566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES));
30949566063dSJacob Faibussowitsch         PetscCall(MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES));
30959566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals));
30964f1b2e48SStefano Zampini       }
30979566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY));
30989566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY));
30996080607fSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!");
3100c263805aSStefano Zampini   }
3101c263805aSStefano Zampini   PetscFunctionReturn(0);
3102c263805aSStefano Zampini }
3103c263805aSStefano Zampini 
310408122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
3105b1b3d7a2SStefano Zampini {
3106b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
310708122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
310808122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
310908122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
311008122e43SStefano Zampini   PetscScalar     *work,lwork;
311108122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
311208122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
3113bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
31141b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
311532fe681dSStefano Zampini   PetscBool       allocated_S_St,upart;
311608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
311708122e43SStefano Zampini   PetscReal       *rwork;
311808122e43SStefano Zampini #endif
3119b1b3d7a2SStefano Zampini 
3120b1b3d7a2SStefano Zampini   PetscFunctionBegin;
312132fe681dSStefano Zampini   if (!pcbddc->adaptive_selection) PetscFunctionReturn(0);
312228b400f6SJacob Faibussowitsch   PetscCheck(sub_schurs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
312332fe681dSStefano Zampini   PetscCheck(sub_schurs->schur_explicit || !sub_schurs->n_subs,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
312432fe681dSStefano Zampini   PetscCheck(!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);
31259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0));
312606a4e24aSStefano Zampini 
3127fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
312832fe681dSStefano Zampini     if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
31299566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
31309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
31319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n"));
31329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
3133fd14bc51SStefano Zampini   }
3134fd14bc51SStefano Zampini 
3135e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
313663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %" PetscInt_FMT " (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef));
3137e496cd5dSStefano Zampini   }
3138e496cd5dSStefano Zampini 
313908122e43SStefano Zampini   /* max size of subsets */
314008122e43SStefano Zampini   mss = 0;
314108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
314208122e43SStefano Zampini     PetscInt subset_size;
3143862806e4SStefano Zampini 
31449566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size));
314508122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
314608122e43SStefano Zampini   }
314708122e43SStefano Zampini 
314808122e43SStefano Zampini   /* min/max and threshold */
314908122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3150f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
315108122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3152f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3153bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3154f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3155f6f667cfSStefano Zampini   }
315608122e43SStefano Zampini 
315708122e43SStefano Zampini   /* allocate lapack workspace */
315808122e43SStefano Zampini   cum = cum2 = 0;
315908122e43SStefano Zampini   maxneigs = 0;
316008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
316108122e43SStefano Zampini     PetscInt n,subset_size;
3162f6f667cfSStefano Zampini 
31639566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size));
316408122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
31659162d606SStefano Zampini     cum += subset_size;
31669162d606SStefano Zampini     cum2 += subset_size*n;
316708122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
316808122e43SStefano Zampini   }
31697ebab0bbSStefano Zampini   lwork = 0;
317008122e43SStefano Zampini   if (mss) {
3171bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
31727ebab0bbSStefano Zampini       PetscScalar  sdummy = 0.;
317308122e43SStefano Zampini       PetscBLASInt B_itype = 1;
31747ebab0bbSStefano Zampini       PetscBLASInt B_N = mss, idummy = 0;
31757ebab0bbSStefano Zampini       PetscReal    rdummy = 0.,zero = 0.0;
31764c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
317708122e43SStefano Zampini 
317808122e43SStefano Zampini       B_lwork = -1;
31797ebab0bbSStefano Zampini       /* some implementations may complain about NULL pointers, even if we are querying */
31807ebab0bbSStefano Zampini       S = &sdummy;
31817ebab0bbSStefano Zampini       St = &sdummy;
31827ebab0bbSStefano Zampini       eigs = &rdummy;
31837ebab0bbSStefano Zampini       eigv = &sdummy;
31847ebab0bbSStefano Zampini       B_iwork = &idummy;
31857ebab0bbSStefano Zampini       B_ifail = &idummy;
3186d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
31877ebab0bbSStefano Zampini       rwork = &rdummy;
3188d1710679SStefano Zampini #endif
31898bec7fa6SStefano Zampini       thresh = 1.0;
31909566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
319108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
319208122e43SStefano 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));
319308122e43SStefano Zampini #else
319408122e43SStefano 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));
319508122e43SStefano Zampini #endif
319608401ef6SPierre Jolivet       PetscCheck(B_ierr == 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
31979566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
3198bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
319908122e43SStefano Zampini   }
320008122e43SStefano Zampini 
320108122e43SStefano Zampini   nv = 0;
3202d62866d3SStefano 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) */
32039566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(sub_schurs->is_vertices,&nv));
320408122e43SStefano Zampini   }
32059566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork));
3206f6f667cfSStefano Zampini   if (allocated_S_St) {
32079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(mss*mss,&S,mss*mss,&St));
3208f6f667cfSStefano Zampini   }
32099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail));
321008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*mss,&rwork));
321208122e43SStefano Zampini #endif
3213d0609cedSBarry Smith   PetscCall(PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
32149162d606SStefano Zampini                          nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
32159162d606SStefano Zampini                          nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
321608122e43SStefano Zampini                          nv+cum,&pcbddc->adaptive_constraints_idxs,
3217d0609cedSBarry Smith                          nv+cum2,&pcbddc->adaptive_constraints_data));
32189566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->adaptive_constraints_n,nv+sub_schurs->n_subs));
321908122e43SStefano Zampini 
322008122e43SStefano Zampini   maxneigs = 0;
322172b8c272SStefano Zampini   cum = cumarray = 0;
32229162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
32239162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3224d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
322508122e43SStefano Zampini     const PetscInt *idxs;
322608122e43SStefano Zampini 
32279566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(sub_schurs->is_vertices,&idxs));
322808122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
322908122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
323008122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
323108122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
32329162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
32339162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
323408122e43SStefano Zampini     }
32359566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(sub_schurs->is_vertices,&idxs));
323608122e43SStefano Zampini   }
323708122e43SStefano Zampini 
323808122e43SStefano Zampini   if (mss) { /* multilevel */
323932fe681dSStefano Zampini     if (sub_schurs->gdsw) {
324032fe681dSStefano Zampini       PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all,&Sarray));
324132fe681dSStefano Zampini       PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray));
324232fe681dSStefano Zampini     } else {
32439566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray));
32449566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray));
324508122e43SStefano Zampini     }
324632fe681dSStefano Zampini   }
324708122e43SStefano Zampini 
3248bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3249bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
325032fe681dSStefano Zampini   upart = pcbddc->use_deluxe_scaling;
325108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
325208122e43SStefano Zampini     const PetscInt *idxs;
32539d54b7f4SStefano Zampini     PetscReal      upper,lower;
3254862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
325508122e43SStefano Zampini     PetscBLASInt   B_N;
3256aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3257bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
325808122e43SStefano Zampini 
325932fe681dSStefano Zampini     if (upart) {
32609d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3261bd2a564bSStefano Zampini       lower = uthresh;
32629d54b7f4SStefano Zampini     } else {
326332fe681dSStefano Zampini       if (sub_schurs->gdsw) {
326432fe681dSStefano Zampini         upper = uthresh;
326532fe681dSStefano Zampini         lower = PETSC_MIN_REAL;
326632fe681dSStefano Zampini       } else {
326728b400f6SJacob Faibussowitsch         PetscCheck(sub_schurs->is_posdef,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling");
3268bd2a564bSStefano Zampini         upper = 1./uthresh;
32699d54b7f4SStefano Zampini         lower = 0.;
32709d54b7f4SStefano Zampini       }
327132fe681dSStefano Zampini     }
32729566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size));
32739566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(sub_schurs->is_subs[i],&idxs));
32749566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(subset_size,&B_N));
3275bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3276bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3277bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3278bd2a564bSStefano Zampini       Mat T;
3279bd2a564bSStefano Zampini 
3280bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3281bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
32829566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T));
32839566063dSJacob Faibussowitsch           PetscCall(MatScale(T,-1.0));
32849566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&T));
32859566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T));
32869566063dSJacob Faibussowitsch           PetscCall(MatScale(T,-1.0));
32879566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&T));
3288bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3289bd2a564bSStefano Zampini             PetscInt       nz,k;
3290bd2a564bSStefano Zampini             const PetscInt *idxs;
3291bd2a564bSStefano Zampini 
32929566063dSJacob Faibussowitsch             PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz));
32939566063dSJacob Faibussowitsch             PetscCall(ISGetIndices(sub_schurs->change_primal_sub[i],&idxs));
3294bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3295bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3296bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3297bd2a564bSStefano Zampini             }
32989566063dSJacob Faibussowitsch             PetscCall(ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs));
3299bd2a564bSStefano Zampini           }
3300bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3301bd2a564bSStefano Zampini           break;
3302bd2a564bSStefano Zampini         }
3303bd2a564bSStefano Zampini       }
3304bd2a564bSStefano Zampini     }
3305bd2a564bSStefano Zampini 
3306f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3307bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3308aff50787SStefano Zampini         PetscInt j,k;
3309580bdb30SBarry Smith         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */
33109566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(S,subset_size*subset_size));
33119566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(St,subset_size*subset_size));
331208122e43SStefano Zampini         }
331308122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3314aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3315aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3316aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3317aff50787SStefano Zampini           }
331808122e43SStefano Zampini         }
331908122e43SStefano Zampini       } else {
33209566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
33219566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
332208122e43SStefano Zampini       }
33238bec7fa6SStefano Zampini     } else {
3324f6f667cfSStefano Zampini       S = Sarray + cumarray;
3325f6f667cfSStefano Zampini       St = Starray + cumarray;
33268bec7fa6SStefano Zampini     }
3327aff50787SStefano Zampini     /* see if we can save some work */
3328b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
33299566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(S,St,subset_size*subset_size,&same_data));
3330aff50787SStefano Zampini     }
3331aff50787SStefano Zampini 
3332b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3333aff50787SStefano Zampini       B_neigs = 0;
3334aff50787SStefano Zampini     } else {
3335bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
333608122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3337f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
33384c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
33399552c7c7SStefano Zampini         PetscInt     nmin_s;
3340bd2a564bSStefano Zampini         PetscBool    compute_range;
3341bd2a564bSStefano Zampini 
33429036ceccSStefano Zampini         B_neigs = 0;
3343bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3344bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
334508122e43SStefano Zampini 
3346fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
33479036ceccSStefano Zampini           PetscInt nc = 0;
3348d16cbb6bSStefano Zampini 
33499036ceccSStefano Zampini           if (sub_schurs->change_primal_sub) {
33509566063dSJacob Faibussowitsch             PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc));
33519036ceccSStefano Zampini           }
335263a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %" PetscInt_FMT "/%" PetscInt_FMT " size %" PetscInt_FMT " count %" PetscInt_FMT " fid %" PetscInt_FMT " (range %d) (change %" PetscInt_FMT ").\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));
3353b7ab4a40SStefano Zampini         }
3354b7ab4a40SStefano Zampini 
33559566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
3356b7ab4a40SStefano Zampini         if (compute_range) {
3357d16cbb6bSStefano Zampini 
3358d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3359bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
336008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
33619d54b7f4SStefano 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));
336208122e43SStefano Zampini #else
33639d54b7f4SStefano 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));
336408122e43SStefano Zampini #endif
33659566063dSJacob Faibussowitsch             PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3366bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
33679036ceccSStefano Zampini             PetscInt  recipe = 0,recipe_m = 1;
3368bd2a564bSStefano Zampini             PetscReal bb[2];
3369bd2a564bSStefano Zampini 
33709566063dSJacob Faibussowitsch             PetscCall(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL));
3371bd2a564bSStefano Zampini             switch (recipe) {
3372bd2a564bSStefano Zampini             case 0:
3373bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3374bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3375bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3376bd2a564bSStefano 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));
3377bd2a564bSStefano Zampini #else
3378bd2a564bSStefano 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));
3379bd2a564bSStefano Zampini #endif
33809566063dSJacob Faibussowitsch               PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3381bd2a564bSStefano Zampini               break;
3382bd2a564bSStefano Zampini             case 1:
3383bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3384bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
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_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
3386bd2a564bSStefano Zampini #else
3387bd2a564bSStefano 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));
3388bd2a564bSStefano Zampini #endif
33899566063dSJacob Faibussowitsch               PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3390bd2a564bSStefano Zampini               if (!scal) {
33919036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
3392bd2a564bSStefano Zampini 
3393aed7e7d0SStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL;
33949566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
33959566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
3396bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3397bd2a564bSStefano 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));
3398bd2a564bSStefano Zampini #else
3399bd2a564bSStefano 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));
3400bd2a564bSStefano Zampini #endif
34019566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3402bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3403bd2a564bSStefano Zampini               }
3404bd2a564bSStefano Zampini               break;
34059036ceccSStefano Zampini             case 2:
34069036ceccSStefano Zampini               if (scal) {
34079036ceccSStefano Zampini                 bb[0] = PETSC_MIN_REAL;
34089036ceccSStefano Zampini                 bb[1] = 0;
34099036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34109036ceccSStefano 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));
34119036ceccSStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
34139036ceccSStefano Zampini #endif
34149566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34159036ceccSStefano Zampini               } else {
34169036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34179036ceccSStefano Zampini                 PetscBool    import = PETSC_FALSE;
34189036ceccSStefano Zampini 
34199036ceccSStefano Zampini                 lthresh = PetscMax(lthresh,0.0);
34209036ceccSStefano Zampini                 if (lthresh > 0.0) {
34219036ceccSStefano Zampini                   bb[0] = PETSC_MIN_REAL;
34229036ceccSStefano Zampini                   bb[1] = lthresh*lthresh;
34239036ceccSStefano Zampini 
34249036ceccSStefano Zampini                   import = PETSC_TRUE;
34259036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34269036ceccSStefano 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));
34279036ceccSStefano Zampini #else
34289036ceccSStefano 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));
34299036ceccSStefano Zampini #endif
34309566063dSJacob Faibussowitsch                   PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34319036ceccSStefano Zampini                 }
34329036ceccSStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh);
34339036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34349036ceccSStefano Zampini                 if (import) {
34359566063dSJacob Faibussowitsch                   PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
34369566063dSJacob Faibussowitsch                   PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
34379036ceccSStefano Zampini                 }
34389036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34399036ceccSStefano 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));
34409036ceccSStefano Zampini #else
34419036ceccSStefano 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));
34429036ceccSStefano Zampini #endif
34439566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34449036ceccSStefano Zampini                 B_neigs += B_neigs2;
34459036ceccSStefano Zampini               }
34469036ceccSStefano Zampini               break;
34479036ceccSStefano Zampini             case 3:
34489036ceccSStefano Zampini               if (scal) {
34499566063dSJacob Faibussowitsch                 PetscCall(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL));
34509036ceccSStefano Zampini               } else {
34519566063dSJacob Faibussowitsch                 PetscCall(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL));
34529036ceccSStefano Zampini               }
34539036ceccSStefano Zampini               if (!scal) {
34549036ceccSStefano Zampini                 bb[0] = uthresh;
34559036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34569036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34579036ceccSStefano 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));
34589036ceccSStefano Zampini #else
34599036ceccSStefano 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));
34609036ceccSStefano Zampini #endif
34619566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34629036ceccSStefano Zampini               }
34639036ceccSStefano Zampini               if (recipe_m > 0 && B_N - B_neigs > 0) {
34649036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34659036ceccSStefano Zampini 
34669036ceccSStefano Zampini                 B_IL = 1;
34679566063dSJacob Faibussowitsch                 PetscCall(PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU));
34689566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
34699566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
34709036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34719036ceccSStefano 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));
34729036ceccSStefano Zampini #else
34739036ceccSStefano 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));
34749036ceccSStefano Zampini #endif
34759566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34769036ceccSStefano Zampini                 B_neigs += B_neigs2;
34779036ceccSStefano Zampini               }
34789036ceccSStefano Zampini               break;
347948cebe81SStefano Zampini             case 4:
348048cebe81SStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh;
348148cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
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_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
348348cebe81SStefano Zampini #else
348448cebe81SStefano 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));
348548cebe81SStefano Zampini #endif
34869566063dSJacob Faibussowitsch               PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
348748cebe81SStefano Zampini               {
348848cebe81SStefano Zampini                 PetscBLASInt B_neigs2 = 0;
348948cebe81SStefano Zampini 
349048cebe81SStefano Zampini                 bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL;
34919566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
34929566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
349348cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
349448cebe81SStefano 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));
349548cebe81SStefano Zampini #else
349648cebe81SStefano 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));
349748cebe81SStefano Zampini #endif
34989566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
349948cebe81SStefano Zampini                 B_neigs += B_neigs2;
350048cebe81SStefano Zampini               }
350148cebe81SStefano Zampini               break;
350280db8efeSStefano Zampini             case 5: /* same as before: first compute all eigenvalues, then filter */
350380db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX)
350480db8efeSStefano 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));
350580db8efeSStefano Zampini #else
350680db8efeSStefano 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));
350780db8efeSStefano Zampini #endif
35089566063dSJacob Faibussowitsch               PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
350980db8efeSStefano Zampini               {
351080db8efeSStefano Zampini                 PetscInt e,k,ne;
351180db8efeSStefano Zampini                 for (e=0,ne=0;e<B_neigs;e++) {
351280db8efeSStefano Zampini                   if (eigs[e] < lthresh || eigs[e] > uthresh) {
351380db8efeSStefano Zampini                     for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k];
351480db8efeSStefano Zampini                     eigs[ne] = eigs[e];
351580db8efeSStefano Zampini                     ne++;
351680db8efeSStefano Zampini                   }
351780db8efeSStefano Zampini                 }
35189566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(eigv,S,B_N*ne));
351980db8efeSStefano Zampini                 B_neigs = ne;
352080db8efeSStefano Zampini               }
352180db8efeSStefano Zampini               break;
3522bd2a564bSStefano Zampini             default:
352363a3b9bcSJacob Faibussowitsch               SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %" PetscInt_FMT,recipe);
3524bd2a564bSStefano Zampini             }
3525bd2a564bSStefano Zampini           }
3526bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3527d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3528d16cbb6bSStefano Zampini           B_IL = 1;
3529d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
35309d54b7f4SStefano 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));
3531d16cbb6bSStefano Zampini #else
35329d54b7f4SStefano 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));
3533d16cbb6bSStefano Zampini #endif
35349566063dSJacob Faibussowitsch           PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3535b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3536b7ab4a40SStefano Zampini           PetscInt k;
353728b400f6SJacob Faibussowitsch           PetscCheck(sub_schurs->change_primal_sub,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
35389566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax));
35399566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(nmax,&B_neigs));
3540b7ab4a40SStefano Zampini           nmin = nmax;
35419566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(eigv,subset_size*nmax));
3542b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3543b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3544b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3545b7ab4a40SStefano Zampini           }
3546d16cbb6bSStefano Zampini         }
35479566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPop());
354808122e43SStefano Zampini         if (B_ierr) {
354963a3b9bcSJacob Faibussowitsch           PetscCheck(B_ierr >= 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT,-B_ierr);
355063a3b9bcSJacob Faibussowitsch           PetscCheck(B_ierr > B_N,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %" PetscBLASInt_FMT " eigenvalues failed to converge",B_ierr);
355163a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %" PetscBLASInt_FMT " is not positive definite",B_ierr-B_N-1);
355208122e43SStefano Zampini         }
355308122e43SStefano Zampini 
355408122e43SStefano Zampini         if (B_neigs > nmax) {
3555fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
355663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %" PetscBLASInt_FMT " eigs, more than maximum required %" PetscInt_FMT ".\n",B_neigs,nmax));
3557fd14bc51SStefano Zampini           }
355832fe681dSStefano Zampini           if (upart) eigs_start = scal ? 0 : B_neigs-nmax;
355908122e43SStefano Zampini           B_neigs = nmax;
356008122e43SStefano Zampini         }
356108122e43SStefano Zampini 
35629552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
35639552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
35649036ceccSStefano Zampini           PetscBLASInt B_neigs2 = 0;
356508122e43SStefano Zampini 
356632fe681dSStefano Zampini           if (upart) {
3567bd2a564bSStefano Zampini             if (scal) {
3568bd2a564bSStefano Zampini               B_IU = nmin_s;
3569bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3570bd2a564bSStefano Zampini             } else {
3571f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
35729d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3573bd2a564bSStefano Zampini             }
35749d54b7f4SStefano Zampini           } else {
35759d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
35769d54b7f4SStefano Zampini             B_IU = nmin_s;
35779d54b7f4SStefano Zampini           }
3578fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
357963a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %" PetscBLASInt_FMT " eigs, less than minimum required %" PetscInt_FMT ". Asking for %" PetscBLASInt_FMT " to %" PetscBLASInt_FMT " incl (fortran like)\n",B_neigs,nmin,B_IL,B_IU));
3580fd14bc51SStefano Zampini           }
3581bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
35821ae86dd6SStefano Zampini             PetscInt j,k;
358308122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
35841ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
35851ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
35861ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
358708122e43SStefano Zampini               }
358808122e43SStefano Zampini             }
358908122e43SStefano Zampini           } else {
35909566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
35919566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
359208122e43SStefano Zampini           }
35939566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
359408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
35959d54b7f4SStefano 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));
359608122e43SStefano Zampini #else
35979d54b7f4SStefano 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));
359808122e43SStefano Zampini #endif
35999566063dSJacob Faibussowitsch           PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
36009566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
360108122e43SStefano Zampini           B_neigs += B_neigs2;
360208122e43SStefano Zampini         }
360308122e43SStefano Zampini         if (B_ierr) {
360463a3b9bcSJacob Faibussowitsch           PetscCheck(B_ierr >= 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT,-B_ierr);
360563a3b9bcSJacob Faibussowitsch           PetscCheck(B_ierr > B_N,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %" PetscBLASInt_FMT " eigenvalues failed to converge",B_ierr);
360663a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %" PetscBLASInt_FMT " is not positive definite",B_ierr-B_N-1);
360708122e43SStefano Zampini         }
3608fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
360963a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %" PetscBLASInt_FMT " eigs\n",B_neigs));
361008122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
361132fe681dSStefano Zampini             if (!sub_schurs->gdsw) {
361208122e43SStefano Zampini               if (eigs[j] == 0.0) {
36139566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n"));
361408122e43SStefano Zampini               } else {
361532fe681dSStefano Zampini                 if (upart) {
361663a3b9bcSJacob Faibussowitsch                   PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",(double)eigs[j+eigs_start]));
36179d54b7f4SStefano Zampini                 } else {
361863a3b9bcSJacob Faibussowitsch                   PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",(double)(1./eigs[j+eigs_start])));
36199d54b7f4SStefano Zampini                 }
3620fd14bc51SStefano Zampini               }
362132fe681dSStefano Zampini             } else {
362232fe681dSStefano Zampini               double pg = (double)eigs[j+eigs_start];
362332fe681dSStefano Zampini               if (pg < 2*PETSC_SMALL) pg = 0.0;
362432fe681dSStefano Zampini               PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",pg));
362532fe681dSStefano Zampini             }
362608122e43SStefano Zampini           }
362708122e43SStefano Zampini         }
3628bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3629aff50787SStefano Zampini     }
36306c3e6151SStefano Zampini     /* change the basis back to the original one */
36316c3e6151SStefano Zampini     if (sub_schurs->change) {
363272b8c272SStefano Zampini       Mat change,phi,phit;
36336c3e6151SStefano Zampini 
363403dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
36356c3e6151SStefano Zampini         PetscInt ii;
36366c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
363763a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n",ii,B_neigs,B_N));
36386c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3639684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3640684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3641684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
364263a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",(double)r,(double)c));
3643684229deSStefano Zampini #else
364463a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",(double)(eigv[(ii+eigs_start)*subset_size+j])));
3645684229deSStefano Zampini #endif
36466c3e6151SStefano Zampini           }
36476c3e6151SStefano Zampini         }
36486c3e6151SStefano Zampini       }
36499566063dSJacob Faibussowitsch       PetscCall(KSPGetOperators(sub_schurs->change[i],&change,NULL));
36509566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit));
36519566063dSJacob Faibussowitsch       PetscCall(MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi));
36529566063dSJacob Faibussowitsch       PetscCall(MatCopy(phi,phit,SAME_NONZERO_PATTERN));
36539566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&phit));
36549566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&phi));
36556c3e6151SStefano Zampini     }
36568bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
36578bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
36589162d606SStefano Zampini     if (B_neigs) {
36599566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size));
3660fd14bc51SStefano Zampini 
3661fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
36629552c7c7SStefano Zampini         PetscInt ii;
36639552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
366463a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n",ii,B_neigs,B_N));
36659552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3666ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3667ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3668ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
366963a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",(double)r,(double)c));
3670ac47001eSStefano Zampini #else
367163a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",(double)PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]])));
3672ac47001eSStefano Zampini #endif
36739552c7c7SStefano Zampini           }
36749552c7c7SStefano Zampini         }
3675fd14bc51SStefano Zampini       }
36769566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size));
36779162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
36789162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
36799162d606SStefano Zampini       cum++;
368008122e43SStefano Zampini     }
36819566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(sub_schurs->is_subs[i],&idxs));
368208122e43SStefano Zampini     /* shift for next computation */
368308122e43SStefano Zampini     cumarray += subset_size*subset_size;
368408122e43SStefano Zampini   }
36851baa6e33SBarry Smith   if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
368608122e43SStefano Zampini 
368708122e43SStefano Zampini   if (mss) {
368832fe681dSStefano Zampini     if (sub_schurs->gdsw) {
368932fe681dSStefano Zampini       PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all,&Sarray));
369032fe681dSStefano Zampini       PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray));
369132fe681dSStefano Zampini     } else {
36929566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray));
36939566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray));
3694f6f667cfSStefano Zampini       /* destroy matrices (junk) */
36959566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_inv_all));
36969566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_tilda_all));
369708122e43SStefano Zampini     }
369832fe681dSStefano Zampini   }
36991baa6e33SBarry Smith   if (allocated_S_St) PetscCall(PetscFree2(S,St));
37009566063dSJacob Faibussowitsch   PetscCall(PetscFree5(eigv,eigs,work,B_iwork,B_ifail));
370108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
37029566063dSJacob Faibussowitsch   PetscCall(PetscFree(rwork));
370308122e43SStefano Zampini #endif
370408122e43SStefano Zampini   if (pcbddc->dbg_flag) {
37051b968477SStefano Zampini     PetscInt maxneigs_r;
37061c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc)));
370763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %" PetscInt_FMT "\n",maxneigs_r));
370808122e43SStefano Zampini   }
37099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0));
371008122e43SStefano Zampini   PetscFunctionReturn(0);
371108122e43SStefano Zampini }
3712b1b3d7a2SStefano Zampini 
3713c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3714c8587f34SStefano Zampini {
37158629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3716c8587f34SStefano Zampini 
3717c8587f34SStefano Zampini   PetscFunctionBegin;
3718f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
37195e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
37209566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalScatters(pc));
3721c8587f34SStefano Zampini 
3722684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
37230fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
37249566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE));
3725c8587f34SStefano Zampini 
37268629588bSStefano Zampini   /*
37278629588bSStefano Zampini      Setup local correction and local part of coarse basis.
37288629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
37298629588bSStefano Zampini   */
37309566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpCorrection(pc,&coarse_submat_vals));
37318629588bSStefano Zampini 
37328629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
37339566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals));
37348629588bSStefano Zampini 
37358629588bSStefano Zampini   /* free */
37369566063dSJacob Faibussowitsch   PetscCall(PetscFree(coarse_submat_vals));
3737c8587f34SStefano Zampini   PetscFunctionReturn(0);
3738c8587f34SStefano Zampini }
3739c8587f34SStefano Zampini 
3740674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3741674ae819SStefano Zampini {
3742674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3743674ae819SStefano Zampini 
3744674ae819SStefano Zampini   PetscFunctionBegin;
37459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
37469566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
37479566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
37489566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
37499566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
37509566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace));
37519566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->onearnullvecs_state));
37529566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
37539566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetDofsSplitting(pc,0,NULL));
37549566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetDofsSplittingLocal(pc,0,NULL));
3755674ae819SStefano Zampini   PetscFunctionReturn(0);
3756674ae819SStefano Zampini }
3757674ae819SStefano Zampini 
3758674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3759674ae819SStefano Zampini {
3760674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37614f1b2e48SStefano Zampini   PetscInt       i;
3762674ae819SStefano Zampini 
3763674ae819SStefano Zampini   PetscFunctionBegin;
37649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->nedcG));
37659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->nedclocal));
37669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->discretegradient));
37679566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
37689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix));
37699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->switch_static_change));
37709566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->work_change));
37719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->ConstraintMatrix));
37729566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->divudotp));
37739566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->divudotp_vl2l));
37749566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphDestroy(&pcbddc->mat_graph));
37754f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
37769566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->local_subs[i]));
37774f1b2e48SStefano Zampini   }
3778e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
37799566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->local_subs));
37809566063dSJacob Faibussowitsch   PetscCall(PCBDDCSubSchursDestroy(&pcbddc->sub_schurs));
3781c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
37828af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
37831c7a958bSStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
3784674ae819SStefano Zampini   PetscFunctionReturn(0);
3785674ae819SStefano Zampini }
3786674ae819SStefano Zampini 
3787674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3788674ae819SStefano Zampini {
3789674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3790674ae819SStefano Zampini 
3791674ae819SStefano Zampini   PetscFunctionBegin;
37929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->coarse_vec));
379358da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3794ca92afb2SStefano Zampini     PetscScalar *array;
37959566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B,&array));
37969566063dSJacob Faibussowitsch     PetscCall(PetscFree(array));
379758da7f69SStefano Zampini   }
37989566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->coarse_phi_B));
37999566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->coarse_phi_D));
38009566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->coarse_psi_B));
38019566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->coarse_psi_D));
38029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->vec1_P));
38039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->vec1_C));
38049566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_auxmat2));
38059566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_auxmat1));
38069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->vec1_R));
38079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->vec2_R));
38089566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->is_R_local));
38099566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcbddc->R_to_B));
38109566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcbddc->R_to_D));
38119566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob));
38129566063dSJacob Faibussowitsch   PetscCall(KSPReset(pcbddc->ksp_D));
38139566063dSJacob Faibussowitsch   PetscCall(KSPReset(pcbddc->ksp_R));
38149566063dSJacob Faibussowitsch   PetscCall(KSPReset(pcbddc->coarse_ksp));
38159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_mat));
38169566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->primal_indices_local_idxs));
38179566063dSJacob Faibussowitsch   PetscCall(PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult));
38189566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->global_primal_indices));
38199566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->coarse_subassembling));
38209566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->benign_change));
38219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->benign_vec));
38229566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc,PETSC_TRUE));
38239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->benign_B0));
38249566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&pcbddc->benign_sf));
3825ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3826ca92afb2SStefano Zampini     PetscInt i;
3827ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
38289566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[i]));
3829ca92afb2SStefano Zampini     }
38309566063dSJacob Faibussowitsch     PetscCall(PetscFree(pcbddc->benign_zerodiag_subs));
3831ca92afb2SStefano Zampini   }
38329566063dSJacob Faibussowitsch   PetscCall(PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0));
3833674ae819SStefano Zampini   PetscFunctionReturn(0);
3834674ae819SStefano Zampini }
3835674ae819SStefano Zampini 
3836f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
38376bfb1811SStefano Zampini {
38386bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
38396bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
38406bfb1811SStefano Zampini   VecType        impVecType;
38414f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
38426bfb1811SStefano Zampini 
38436bfb1811SStefano Zampini   PetscFunctionBegin;
38444f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3845b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
38469566063dSJacob Faibussowitsch   PetscCall(VecGetType(pcis->vec1_N,&impVecType));
3847e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3848e7b262bdSStefano Zampini   /* R nodes */
3849e7b262bdSStefano Zampini   old_size = -1;
3850e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
38519566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcbddc->vec1_R,&old_size));
3852e7b262bdSStefano Zampini   }
3853e7b262bdSStefano Zampini   if (n_R != old_size) {
38549566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->vec1_R));
38559566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->vec2_R));
38569566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R));
38579566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R));
38589566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcbddc->vec1_R,impVecType));
38599566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R));
3860e7b262bdSStefano Zampini   }
3861e7b262bdSStefano Zampini   /* local primal dofs */
3862e7b262bdSStefano Zampini   old_size = -1;
3863e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
38649566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcbddc->vec1_P,&old_size));
3865e7b262bdSStefano Zampini   }
3866e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
38679566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->vec1_P));
38689566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P));
38699566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size));
38709566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcbddc->vec1_P,impVecType));
3871e7b262bdSStefano Zampini   }
3872e7b262bdSStefano Zampini   /* local explicit constraints */
3873e7b262bdSStefano Zampini   old_size = -1;
3874e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
38759566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcbddc->vec1_C,&old_size));
3876e7b262bdSStefano Zampini   }
3877e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
38789566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->vec1_C));
38799566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C));
38809566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints));
38819566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcbddc->vec1_C,impVecType));
388283b7ccabSStefano Zampini   }
38836bfb1811SStefano Zampini   PetscFunctionReturn(0);
38846bfb1811SStefano Zampini }
38856bfb1811SStefano Zampini 
388647f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
388788ebb749SStefano Zampini {
388825084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
388988ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
389088ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3891d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
389225084f0cSStefano Zampini   /* submatrices of local problem */
389380677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
389406656605SStefano Zampini   /* submatrices of local coarse problem */
389506656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
389625084f0cSStefano Zampini   /* working matrices */
389706656605SStefano Zampini   Mat             C_CR;
389825084f0cSStefano Zampini   /* additional working stuff */
389906656605SStefano Zampini   PC              pc_R;
3900c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
39015cbda25cSStefano Zampini   Vec             dummy_vec;
39027ebab0bbSStefano Zampini   PetscBool       isLU,isCHOL,need_benign_correction,sparserhs;
390325084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
390406656605SStefano Zampini   PetscScalar     *work;
390506656605SStefano Zampini   PetscInt        *idx_V_B;
3906ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
390706656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
390806656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
390988ebb749SStefano Zampini 
391088ebb749SStefano Zampini   PetscFunctionBegin;
39117827d75bSBarry Smith   PetscCheck(pcbddc->symmetric_primal || !pcbddc->benign_n,PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
39129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0));
3913ffd830a3SStefano Zampini 
3914ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3915b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
39164f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3917b371cd4fSStefano Zampini   n_B = pcis->n_B;
3918b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
391988ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
392088ebb749SStefano Zampini 
392188ebb749SStefano Zampini   /* vertices in boundary numbering */
39229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_vertices,&idx_V_B));
39239566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B));
392463a3b9bcSJacob Faibussowitsch   PetscCheck(i == n_vertices,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %" PetscInt_FMT " != %" PetscInt_FMT,n_vertices,i);
392588ebb749SStefano Zampini 
392606656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
39279566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals));
39289566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV));
39299566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(S_VV,pcbddc->local_primal_size));
39309566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV));
39319566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(S_CV,pcbddc->local_primal_size));
39329566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC));
39339566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(S_VC,pcbddc->local_primal_size));
39349566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC));
39359566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(S_CC,pcbddc->local_primal_size));
393606656605SStefano Zampini 
393706656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
39389566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(pcbddc->ksp_R,&pc_R));
39399566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc_R));
39409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU));
39419566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL));
3942ffd830a3SStefano Zampini   lda_rhs = n_R;
3943a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
39447ebab0bbSStefano Zampini   if (isLU || isCHOL) {
39459566063dSJacob Faibussowitsch     PetscCall(PCFactorGetMatrix(pc_R,&F));
3946b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3947df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3948d62866d3SStefano Zampini     MatFactorType      type;
3949d62866d3SStefano Zampini 
3950df4d28bfSStefano Zampini     F = reuse_solver->F;
39519566063dSJacob Faibussowitsch     PetscCall(MatGetFactorType(F,&type));
3952d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
39537ebab0bbSStefano Zampini     if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE;
39549566063dSJacob Faibussowitsch     PetscCall(MatGetSize(F,&lda_rhs,NULL));
395522db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
39567ebab0bbSStefano Zampini   } else F = NULL;
395706656605SStefano Zampini 
3958c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3959c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3960c58f9fdbSStefano Zampini   if (F) {
3961ea799195SBarry Smith     MatSolverType solver;
3962c58f9fdbSStefano Zampini 
39639566063dSJacob Faibussowitsch     PetscCall(MatFactorGetSolverType(F,&solver));
39649566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs));
3965c58f9fdbSStefano Zampini   }
3966c58f9fdbSStefano Zampini 
3967ffd830a3SStefano Zampini   /* allocate workspace */
3968ffd830a3SStefano Zampini   n = 0;
3969ffd830a3SStefano Zampini   if (n_constraints) {
3970ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3971ffd830a3SStefano Zampini   }
3972ffd830a3SStefano Zampini   if (n_vertices) {
3973ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3974ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3975ffd830a3SStefano Zampini   }
39762a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
39772a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
39782a3a6641Sstefano_zampini   }
39799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n,&work));
3980ffd830a3SStefano Zampini 
39815cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
39825cbda25cSStefano Zampini   dummy_vec = NULL;
39835cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
39849566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&dummy_vec));
39859566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(dummy_vec,lda_rhs,PETSC_DECIDE));
39869566063dSJacob Faibussowitsch     PetscCall(VecSetType(dummy_vec,((PetscObject)pcis->vec1_N)->type_name));
39875cbda25cSStefano Zampini   }
39885cbda25cSStefano Zampini 
39899566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_auxmat1));
39909566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_auxmat2));
39917ebab0bbSStefano Zampini 
399288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
399388ebb749SStefano Zampini   if (n_constraints) {
3994837cedc9SStefano Zampini     Mat         M3,C_B;
399506656605SStefano Zampini     IS          is_aux;
399606656605SStefano Zampini 
399725084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
39989566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux));
39999566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR));
40009566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B));
400188ebb749SStefano Zampini 
400280677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
400380677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
4004c58f9fdbSStefano Zampini     if (!sparserhs) {
40059566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(work,lda_rhs*n_constraints));
400688ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
400706656605SStefano Zampini         const PetscScalar *row_cmat_values;
400806656605SStefano Zampini         const PetscInt    *row_cmat_indices;
400906656605SStefano Zampini         PetscInt          size_of_constraint,j;
401088ebb749SStefano Zampini 
40119566063dSJacob Faibussowitsch         PetscCall(MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values));
401206656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
4013ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
401406656605SStefano Zampini         }
40159566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values));
401606656605SStefano Zampini       }
40179566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs));
4018c58f9fdbSStefano Zampini     } else {
4019c58f9fdbSStefano Zampini       Mat tC_CR;
4020c58f9fdbSStefano Zampini 
40219566063dSJacob Faibussowitsch       PetscCall(MatScale(C_CR,-1.0));
4022c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
4023c58f9fdbSStefano Zampini         PetscScalar *aa;
4024c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
4025c58f9fdbSStefano Zampini         PetscBool   done;
4026c58f9fdbSStefano Zampini 
40279566063dSJacob Faibussowitsch         PetscCall(MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done));
402828b400f6SJacob Faibussowitsch         PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
40299566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJGetArray(C_CR,&aa));
40309566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR));
40319566063dSJacob Faibussowitsch         PetscCall(MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done));
403228b400f6SJacob Faibussowitsch         PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4033c58f9fdbSStefano Zampini       } else {
40349566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)C_CR));
4035c58f9fdbSStefano Zampini         tC_CR = C_CR;
4036c58f9fdbSStefano Zampini       }
40379566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(tC_CR,&Brhs));
40389566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&tC_CR));
4039c58f9fdbSStefano Zampini     }
40409566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R));
404106656605SStefano Zampini     if (F) {
4042a3df083aSStefano Zampini       if (need_benign_correction) {
4043df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4044a3df083aSStefano Zampini 
404572b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
40469566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(reuse_solver->benign_save_vals,pcbddc->benign_n));
4047a3df083aSStefano Zampini       }
40489566063dSJacob Faibussowitsch       PetscCall(MatMatSolve(F,Brhs,local_auxmat2_R));
4049a3df083aSStefano Zampini       if (need_benign_correction) {
4050a3df083aSStefano Zampini         PetscScalar        *marr;
4051df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4052a3df083aSStefano Zampini 
40539566063dSJacob Faibussowitsch         PetscCall(MatDenseGetArray(local_auxmat2_R,&marr));
40545cbda25cSStefano Zampini         if (lda_rhs != n_R) {
40555cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
40569566063dSJacob Faibussowitsch             PetscCall(VecPlaceArray(dummy_vec,marr+i*lda_rhs));
40579566063dSJacob Faibussowitsch             PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE));
40589566063dSJacob Faibussowitsch             PetscCall(VecResetArray(dummy_vec));
40595cbda25cSStefano Zampini           }
40605cbda25cSStefano Zampini         } else {
4061a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
40629566063dSJacob Faibussowitsch             PetscCall(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs));
40639566063dSJacob Faibussowitsch             PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE));
40649566063dSJacob Faibussowitsch             PetscCall(VecResetArray(pcbddc->vec1_R));
4065a3df083aSStefano Zampini           }
40665cbda25cSStefano Zampini         }
40679566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreArray(local_auxmat2_R,&marr));
4068a3df083aSStefano Zampini       }
406906656605SStefano Zampini     } else {
407080677318SStefano Zampini       PetscScalar *marr;
407180677318SStefano Zampini 
40729566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(local_auxmat2_R,&marr));
407306656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
40749566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs));
40759566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs));
40769566063dSJacob Faibussowitsch         PetscCall(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R));
40779566063dSJacob Faibussowitsch         PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
40789566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec1_R));
40799566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec2_R));
408006656605SStefano Zampini       }
40819566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(local_auxmat2_R,&marr));
408206656605SStefano Zampini     }
40831baa6e33SBarry Smith     if (sparserhs) PetscCall(MatScale(C_CR,-1.0));
40849566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Brhs));
408580677318SStefano Zampini     if (!pcbddc->switch_static) {
40869566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2));
408780677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
4088ab2d12f3SJunchao Zhang         Vec r, b;
40899566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVecRead(local_auxmat2_R,i,&r));
40909566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVec(pcbddc->local_auxmat2,i,&b));
40919566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcbddc->R_to_B,r,b,INSERT_VALUES,SCATTER_FORWARD));
40929566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcbddc->R_to_B,r,b,INSERT_VALUES,SCATTER_FORWARD));
40939566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVec(pcbddc->local_auxmat2,i,&b));
40949566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVecRead(local_auxmat2_R,i,&r));
409580677318SStefano Zampini       }
40969566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3));
409780677318SStefano Zampini     } else {
4098ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4099ffd830a3SStefano Zampini         IS dummy;
4100ffd830a3SStefano Zampini 
41019566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy));
41029566063dSJacob Faibussowitsch         PetscCall(MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2));
41039566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&dummy));
4104ffd830a3SStefano Zampini       } else {
41059566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)local_auxmat2_R));
410680677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
4107ffd830a3SStefano Zampini       }
41089566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3));
410980677318SStefano Zampini     }
41109566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_aux));
411180677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1}  */
41129566063dSJacob Faibussowitsch     PetscCall(MatScale(M3,m_one));
411380677318SStefano Zampini     if (isCHOL) {
41149566063dSJacob Faibussowitsch       PetscCall(MatCholeskyFactor(M3,NULL,NULL));
411580677318SStefano Zampini     } else {
41169566063dSJacob Faibussowitsch       PetscCall(MatLUFactor(M3,NULL,NULL,NULL));
411780677318SStefano Zampini     }
41189566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseInvertFactors_Private(M3));
411980677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
41209566063dSJacob Faibussowitsch     PetscCall(MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1));
41219566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C_B));
41229566063dSJacob Faibussowitsch     PetscCall(MatCopy(M3,S_CC,SAME_NONZERO_PATTERN)); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
41239566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&M3));
4124f4ddd8eeSStefano Zampini   }
4125fc227af8SStefano Zampini 
4126fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
412788ebb749SStefano Zampini   if (n_vertices) {
41287ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
41297ebab0bbSStefano Zampini     PetscBool oldpin;
41307ebab0bbSStefano Zampini #endif
41317ebab0bbSStefano Zampini     PetscBool isaij;
413206656605SStefano Zampini     IS        is_aux;
41333a50541eSStefano Zampini 
4134b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
41356816873aSStefano Zampini       IS tis;
41366816873aSStefano Zampini 
41379566063dSJacob Faibussowitsch       PetscCall(ISDuplicate(pcbddc->is_R_local,&tis));
41389566063dSJacob Faibussowitsch       PetscCall(ISSort(tis));
41399566063dSJacob Faibussowitsch       PetscCall(ISComplement(tis,0,pcis->n,&is_aux));
41409566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&tis));
41416816873aSStefano Zampini     } else {
41429566063dSJacob Faibussowitsch       PetscCall(ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux));
41436816873aSStefano Zampini     }
41447ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
4145b470e4b4SRichard Tran Mills     oldpin = pcbddc->local_mat->boundtocpu;
41467ebab0bbSStefano Zampini #endif
41479566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(pcbddc->local_mat,PETSC_TRUE));
41489566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV));
41499566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR));
41509566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isaij));
41517ebab0bbSStefano Zampini     if (!isaij) { /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */
41529566063dSJacob Faibussowitsch       PetscCall(MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR));
41537ebab0bbSStefano Zampini     }
41549566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV));
41557ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
41569566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(pcbddc->local_mat,oldpin));
41577ebab0bbSStefano Zampini #endif
41589566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_aux));
415988ebb749SStefano Zampini   }
416088ebb749SStefano Zampini 
416188ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
4162f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
416306656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
416406656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
41659566063dSJacob Faibussowitsch       PetscCall(MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL));
416606656605SStefano Zampini     }
41679566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal));
416806656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
416906656605SStefano Zampini       PetscScalar *marray;
417006656605SStefano Zampini 
41719566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B,&marray));
41729566063dSJacob Faibussowitsch       PetscCall(PetscFree(marray));
41739566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->coarse_phi_B));
41749566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->coarse_psi_B));
41759566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->coarse_phi_D));
41769566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->coarse_psi_D));
4177f4ddd8eeSStefano Zampini     }
4178f4ddd8eeSStefano Zampini   }
417906656605SStefano Zampini 
4180f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
4181a6e023c1Sstefano_zampini     PetscScalar *marr;
418288ebb749SStefano Zampini 
4183a6e023c1Sstefano_zampini     /* memory size */
418406656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
4185a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
4186a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
41879566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n,&marr));
41889566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B));
4189a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
41908eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
41919566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D));
4192a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
419388ebb749SStefano Zampini     }
41943301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
41959566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B));
4196a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
41978eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
41989566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D));
419988ebb749SStefano Zampini       }
420088ebb749SStefano Zampini     } else {
42019566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_B));
4202c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
42031b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
42049566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_D));
4205c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
4206c0553b1fSStefano Zampini       }
420788ebb749SStefano Zampini     }
420806656605SStefano Zampini   }
4209019a44ceSStefano Zampini 
421006656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
42114f1b2e48SStefano Zampini   p0_lidx_I = NULL;
42124f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
4213d12edf2fSStefano Zampini     const PetscInt *idxs;
4214d12edf2fSStefano Zampini 
42159566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcis->is_I_local,&idxs));
42169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcbddc->benign_n,&p0_lidx_I));
42174f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
42189566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]));
42194f1b2e48SStefano Zampini     }
42209566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcis->is_I_local,&idxs));
4221d12edf2fSStefano Zampini   }
4222d16cbb6bSStefano Zampini 
422306656605SStefano Zampini   /* vertices */
422406656605SStefano Zampini   if (n_vertices) {
4225c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
422616f15bc4SStefano Zampini 
42279566063dSJacob Faibussowitsch     PetscCall(MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV));
422804708bb6SStefano Zampini 
422916f15bc4SStefano Zampini     if (n_R) {
423014393ed6SStefano Zampini       Mat               A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
423106656605SStefano Zampini       PetscBLASInt      B_N,B_one = 1;
42321683a169SBarry Smith       const PetscScalar *x;
42331683a169SBarry Smith       PetscScalar       *y;
423406656605SStefano Zampini 
42359566063dSJacob Faibussowitsch       PetscCall(MatScale(A_RV,m_one));
423614393ed6SStefano Zampini       if (need_benign_correction) {
423714393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
423814393ed6SStefano Zampini         IS                     is_p0;
423914393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
424014393ed6SStefano Zampini 
42419566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(pcbddc->benign_n,&idxs_p0));
42429566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN));
42439566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0));
424463a3b9bcSJacob Faibussowitsch         PetscCheck(n == pcbddc->benign_n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %" PetscInt_FMT " != %" PetscInt_FMT,n,pcbddc->benign_n);
42459566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingDestroy(&RtoN));
42469566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0));
42479566063dSJacob Faibussowitsch         PetscCall(MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr));
42489566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&is_p0));
424914393ed6SStefano Zampini       }
425014393ed6SStefano Zampini 
42519566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV));
4252c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
4253ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
42549566063dSJacob Faibussowitsch           PetscCall(MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV));
4255ffd830a3SStefano Zampini         } else {
4256ca92afb2SStefano Zampini           PetscScalar    *av,*array;
4257ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
4258ca92afb2SStefano Zampini           PetscInt       n;
4259ca92afb2SStefano Zampini           PetscBool      flg_row;
4260ffd830a3SStefano Zampini 
4261ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
42629566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(array,lda_rhs*n_vertices));
42639566063dSJacob Faibussowitsch           PetscCall(MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV));
42649566063dSJacob Faibussowitsch           PetscCall(MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row));
42659566063dSJacob Faibussowitsch           PetscCall(MatSeqAIJGetArray(A_RV,&av));
4266ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
4267ca92afb2SStefano Zampini             PetscInt j;
4268ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
4269ffd830a3SStefano Zampini           }
42709566063dSJacob Faibussowitsch           PetscCall(MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row));
42719566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&A_RV));
42729566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV));
4273ffd830a3SStefano Zampini         }
4274a3df083aSStefano Zampini         if (need_benign_correction) {
4275df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4276a3df083aSStefano Zampini           PetscScalar        *marr;
4277a3df083aSStefano Zampini 
42789566063dSJacob Faibussowitsch           PetscCall(MatDenseGetArray(A_RV,&marr));
427914393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
428014393ed6SStefano Zampini 
428114393ed6SStefano Zampini                  | 0 0  0 | (V)
428214393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
428314393ed6SStefano Zampini                  | 0 0 -1 | (p0)
428414393ed6SStefano Zampini 
428514393ed6SStefano Zampini           */
4286df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
428714393ed6SStefano Zampini             const PetscScalar *vals;
428814393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
428914393ed6SStefano Zampini             PetscInt          n,j,nz;
429014393ed6SStefano Zampini 
42919566063dSJacob Faibussowitsch             PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz));
42929566063dSJacob Faibussowitsch             PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero));
42939566063dSJacob Faibussowitsch             PetscCall(MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals));
429414393ed6SStefano Zampini             for (j=0;j<n;j++) {
429514393ed6SStefano Zampini               PetscScalar val = vals[j];
429614393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
429714393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
429814393ed6SStefano Zampini             }
42999566063dSJacob Faibussowitsch             PetscCall(MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals));
43009566063dSJacob Faibussowitsch             PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero));
430114393ed6SStefano Zampini           }
43029566063dSJacob Faibussowitsch           PetscCall(MatDenseRestoreArray(A_RV,&marr));
430372b8c272SStefano Zampini         }
43049566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A_RV));
4305c58f9fdbSStefano Zampini         Brhs = A_RV;
4306c58f9fdbSStefano Zampini       } else {
4307c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4308c58f9fdbSStefano Zampini 
4309c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4310fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
43119566063dSJacob Faibussowitsch           PetscCall(MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT));
4312c58f9fdbSStefano Zampini         } else {
4313c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
43149566063dSJacob Faibussowitsch           PetscCall(MatScale(A_VR,-1.0));
43159566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)A_VR));
4316c58f9fdbSStefano Zampini           A_RVT = A_VR;
4317c58f9fdbSStefano Zampini         }
4318c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4319c58f9fdbSStefano Zampini           PetscScalar *aa;
4320c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4321c58f9fdbSStefano Zampini           PetscBool   done;
4322c58f9fdbSStefano Zampini 
43239566063dSJacob Faibussowitsch           PetscCall(MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done));
432428b400f6SJacob Faibussowitsch           PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
43259566063dSJacob Faibussowitsch           PetscCall(MatSeqAIJGetArray(A_RVT,&aa));
43269566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT));
43279566063dSJacob Faibussowitsch           PetscCall(MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done));
432828b400f6SJacob Faibussowitsch           PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4329c58f9fdbSStefano Zampini         } else {
43309566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)A_RVT));
4331c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4332c58f9fdbSStefano Zampini         }
43339566063dSJacob Faibussowitsch         PetscCall(MatCreateTranspose(tA_RVT,&Brhs));
43349566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&tA_RVT));
43359566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RVT));
4336c58f9fdbSStefano Zampini       }
433772b8c272SStefano Zampini       if (F) {
433814393ed6SStefano Zampini         /* need to correct the rhs */
433972b8c272SStefano Zampini         if (need_benign_correction) {
434072b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
434172b8c272SStefano Zampini           PetscScalar        *marr;
434272b8c272SStefano Zampini 
43439566063dSJacob Faibussowitsch           PetscCall(MatDenseGetArray(Brhs,&marr));
43445cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43455cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43469566063dSJacob Faibussowitsch               PetscCall(VecPlaceArray(dummy_vec,marr+i*lda_rhs));
43479566063dSJacob Faibussowitsch               PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE));
43489566063dSJacob Faibussowitsch               PetscCall(VecResetArray(dummy_vec));
43495cbda25cSStefano Zampini             }
43505cbda25cSStefano Zampini           } else {
4351a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
43529566063dSJacob Faibussowitsch               PetscCall(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs));
43539566063dSJacob Faibussowitsch               PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE));
43549566063dSJacob Faibussowitsch               PetscCall(VecResetArray(pcbddc->vec1_R));
4355a3df083aSStefano Zampini             }
43565cbda25cSStefano Zampini           }
43579566063dSJacob Faibussowitsch           PetscCall(MatDenseRestoreArray(Brhs,&marr));
4358a3df083aSStefano Zampini         }
43599566063dSJacob Faibussowitsch         PetscCall(MatMatSolve(F,Brhs,A_RRmA_RV));
43601baa6e33SBarry Smith         if (restoreavr) PetscCall(MatScale(A_VR,-1.0));
436114393ed6SStefano Zampini         /* need to correct the solution */
4362a3df083aSStefano Zampini         if (need_benign_correction) {
4363df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4364a3df083aSStefano Zampini           PetscScalar        *marr;
4365a3df083aSStefano Zampini 
43669566063dSJacob Faibussowitsch           PetscCall(MatDenseGetArray(A_RRmA_RV,&marr));
43675cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43685cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43699566063dSJacob Faibussowitsch               PetscCall(VecPlaceArray(dummy_vec,marr+i*lda_rhs));
43709566063dSJacob Faibussowitsch               PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE));
43719566063dSJacob Faibussowitsch               PetscCall(VecResetArray(dummy_vec));
43725cbda25cSStefano Zampini             }
43735cbda25cSStefano Zampini           } else {
4374a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
43759566063dSJacob Faibussowitsch               PetscCall(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs));
43769566063dSJacob Faibussowitsch               PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE));
43779566063dSJacob Faibussowitsch               PetscCall(VecResetArray(pcbddc->vec1_R));
4378a3df083aSStefano Zampini             }
43795cbda25cSStefano Zampini           }
43809566063dSJacob Faibussowitsch           PetscCall(MatDenseRestoreArray(A_RRmA_RV,&marr));
4381a3df083aSStefano Zampini         }
438206656605SStefano Zampini       } else {
43839566063dSJacob Faibussowitsch         PetscCall(MatDenseGetArray(Brhs,&y));
438406656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
43859566063dSJacob Faibussowitsch           PetscCall(VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs));
43869566063dSJacob Faibussowitsch           PetscCall(VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs));
43879566063dSJacob Faibussowitsch           PetscCall(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R));
43889566063dSJacob Faibussowitsch           PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
43899566063dSJacob Faibussowitsch           PetscCall(VecResetArray(pcbddc->vec1_R));
43909566063dSJacob Faibussowitsch           PetscCall(VecResetArray(pcbddc->vec2_R));
439106656605SStefano Zampini         }
43929566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreArray(Brhs,&y));
439306656605SStefano Zampini       }
43949566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A_RV));
43959566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Brhs));
4396ffd830a3SStefano Zampini       /* S_VV and S_CV */
439706656605SStefano Zampini       if (n_constraints) {
439806656605SStefano Zampini         Mat B;
439980677318SStefano Zampini 
44009566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(work+lda_rhs*n_vertices,n_B*n_vertices));
440180677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
44029566063dSJacob Faibussowitsch           PetscCall(VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs));
44039566063dSJacob Faibussowitsch           PetscCall(VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B));
44049566063dSJacob Faibussowitsch           PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
44059566063dSJacob Faibussowitsch           PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
44069566063dSJacob Faibussowitsch           PetscCall(VecResetArray(pcis->vec1_B));
44079566063dSJacob Faibussowitsch           PetscCall(VecResetArray(pcbddc->vec1_R));
440880677318SStefano Zampini         }
44099566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B));
44104222ddf1SHong Zhang         /* Reuse dense S_C = pcbddc->local_auxmat1 * B */
44119566063dSJacob Faibussowitsch         PetscCall(MatProductCreateWithMat(pcbddc->local_auxmat1,B,NULL,S_CV));
44129566063dSJacob Faibussowitsch         PetscCall(MatProductSetType(S_CV,MATPRODUCT_AB));
44139566063dSJacob Faibussowitsch         PetscCall(MatProductSetFromOptions(S_CV));
44149566063dSJacob Faibussowitsch         PetscCall(MatProductSymbolic(S_CV));
44159566063dSJacob Faibussowitsch         PetscCall(MatProductNumeric(S_CV));
44169566063dSJacob Faibussowitsch         PetscCall(MatProductClear(S_CV));
44174222ddf1SHong Zhang 
44189566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&B));
44199566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B));
44204222ddf1SHong Zhang         /* Reuse B = local_auxmat2_R * S_CV */
44219566063dSJacob Faibussowitsch         PetscCall(MatProductCreateWithMat(local_auxmat2_R,S_CV,NULL,B));
44229566063dSJacob Faibussowitsch         PetscCall(MatProductSetType(B,MATPRODUCT_AB));
44239566063dSJacob Faibussowitsch         PetscCall(MatProductSetFromOptions(B));
44249566063dSJacob Faibussowitsch         PetscCall(MatProductSymbolic(B));
44259566063dSJacob Faibussowitsch         PetscCall(MatProductNumeric(B));
44264222ddf1SHong Zhang 
44279566063dSJacob Faibussowitsch         PetscCall(MatScale(S_CV,m_one));
44289566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(lda_rhs*n_vertices,&B_N));
4429ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
44309566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&B));
443106656605SStefano Zampini       }
4432ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
44339566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RRmA_RV));
44349566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV));
44359566063dSJacob Faibussowitsch         PetscCall(MatDenseSetLDA(A_RRmA_RV,lda_rhs));
4436ffd830a3SStefano Zampini       }
44379566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt));
443814393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
443914393ed6SStefano Zampini       if (need_benign_correction) {
4440df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
444114393ed6SStefano Zampini         PetscScalar        *marr,*sums;
444214393ed6SStefano Zampini 
44439566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(n_vertices,&sums));
44449566063dSJacob Faibussowitsch         PetscCall(MatDenseGetArray(S_VVt,&marr));
4445df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
444614393ed6SStefano Zampini           const PetscScalar *vals;
444714393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
444814393ed6SStefano Zampini           PetscInt          n,j,nz;
444914393ed6SStefano Zampini 
44509566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz));
44519566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero));
445214393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
445314393ed6SStefano Zampini             PetscInt k;
445414393ed6SStefano Zampini             sums[j] = 0.;
445514393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
445614393ed6SStefano Zampini           }
44579566063dSJacob Faibussowitsch           PetscCall(MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals));
445814393ed6SStefano Zampini           for (j=0;j<n;j++) {
445914393ed6SStefano Zampini             PetscScalar val = vals[j];
446014393ed6SStefano Zampini             PetscInt k;
446114393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
446214393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
446314393ed6SStefano Zampini             }
446414393ed6SStefano Zampini           }
44659566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals));
44669566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero));
446714393ed6SStefano Zampini         }
44689566063dSJacob Faibussowitsch         PetscCall(PetscFree(sums));
44699566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreArray(S_VVt,&marr));
44709566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RV_bcorr));
447114393ed6SStefano Zampini       }
44729566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A_RRmA_RV));
44739566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(n_vertices*n_vertices,&B_N));
44749566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(A_VV,&x));
44759566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(S_VVt,&y));
447606656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
44779566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(A_VV,&x));
44789566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(S_VVt,&y));
44799566063dSJacob Faibussowitsch       PetscCall(MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN));
44809566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&S_VVt));
4481019a44ceSStefano Zampini     } else {
44829566063dSJacob Faibussowitsch       PetscCall(MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN));
4483d16cbb6bSStefano Zampini     }
44849566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_VV));
4485d16cbb6bSStefano Zampini 
448606656605SStefano Zampini     /* coarse basis functions */
448706656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
4488ab2d12f3SJunchao Zhang       Vec         v;
4489ab2d12f3SJunchao Zhang       PetscScalar one = 1.0,zero = 0.0;
449016f15bc4SStefano Zampini 
44919566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i));
44929566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_B,i,&v));
44939566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
44949566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
4495ab2d12f3SJunchao Zhang       if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */
4496ab2d12f3SJunchao Zhang         PetscMPIInt rank;
44979566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_B),&rank));
449808401ef6SPierre Jolivet         PetscCheck(rank <= 1,PetscObjectComm((PetscObject)pcbddc->coarse_phi_B),PETSC_ERR_PLIB,"Expected a sequential dense matrix");
4499ab2d12f3SJunchao Zhang       }
45009566063dSJacob Faibussowitsch       PetscCall(VecSetValues(v,1,&idx_V_B[i],&one,INSERT_VALUES));
45019566063dSJacob Faibussowitsch       PetscCall(VecAssemblyBegin(v)); /* If v is on device, hope VecSetValues() eventually implemented by a host to device memcopy */
45029566063dSJacob Faibussowitsch       PetscCall(VecAssemblyEnd(v));
45039566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B,i,&v));
450406656605SStefano Zampini 
450506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45064f1b2e48SStefano Zampini         PetscInt j;
45074f1b2e48SStefano Zampini 
45089566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_D,i,&v));
45099566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45109566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
4511ab2d12f3SJunchao Zhang         if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */
4512ab2d12f3SJunchao Zhang           PetscMPIInt rank;
45139566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_D),&rank));
451408401ef6SPierre Jolivet           PetscCheck(rank <= 1,PetscObjectComm((PetscObject)pcbddc->coarse_phi_D),PETSC_ERR_PLIB,"Expected a sequential dense matrix");
4515ab2d12f3SJunchao Zhang         }
45169566063dSJacob Faibussowitsch         for (j=0;j<pcbddc->benign_n;j++) PetscCall(VecSetValues(v,1,&p0_lidx_I[j],&zero,INSERT_VALUES));
45179566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(v));
45189566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(v));
45199566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D,i,&v));
452006656605SStefano Zampini       }
45219566063dSJacob Faibussowitsch       PetscCall(VecResetArray(pcbddc->vec1_R));
452206656605SStefano Zampini     }
452304708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
45249566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_RV));
452506656605SStefano Zampini   }
45269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&dummy_vec));
452706656605SStefano Zampini 
452806656605SStefano Zampini   if (n_constraints) {
452906656605SStefano Zampini     Mat B;
453006656605SStefano Zampini 
45319566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B));
45329566063dSJacob Faibussowitsch     PetscCall(MatScale(S_CC,m_one));
45339566063dSJacob Faibussowitsch     PetscCall(MatProductCreateWithMat(local_auxmat2_R,S_CC,NULL,B));
45349566063dSJacob Faibussowitsch     PetscCall(MatProductSetType(B,MATPRODUCT_AB));
45359566063dSJacob Faibussowitsch     PetscCall(MatProductSetFromOptions(B));
45369566063dSJacob Faibussowitsch     PetscCall(MatProductSymbolic(B));
45379566063dSJacob Faibussowitsch     PetscCall(MatProductNumeric(B));
4538a961b312SStefano Zampini 
45399566063dSJacob Faibussowitsch     PetscCall(MatScale(S_CC,m_one));
454006656605SStefano Zampini     if (n_vertices) {
454103dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
45429566063dSJacob Faibussowitsch         PetscCall(MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC));
454380677318SStefano Zampini       } else {
454480677318SStefano Zampini         Mat S_VCt;
454580677318SStefano Zampini 
4546ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
45479566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&B));
45489566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B));
45499566063dSJacob Faibussowitsch           PetscCall(MatDenseSetLDA(B,lda_rhs));
4550ffd830a3SStefano Zampini         }
45519566063dSJacob Faibussowitsch         PetscCall(MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt));
45529566063dSJacob Faibussowitsch         PetscCall(MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN));
45539566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&S_VCt));
455480677318SStefano Zampini       }
455506656605SStefano Zampini     }
45569566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
455706656605SStefano Zampini     /* coarse basis functions */
455806656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
4559ab2d12f3SJunchao Zhang       Vec v;
456006656605SStefano Zampini 
45619566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i));
45629566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_B,i+n_vertices,&v));
45639566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45649566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45659566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B,i+n_vertices,&v));
456606656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45674f1b2e48SStefano Zampini         PetscInt    j;
4568ab2d12f3SJunchao Zhang         PetscScalar zero = 0.0;
45699566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_D,i+n_vertices,&v));
45709566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45719566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45729566063dSJacob Faibussowitsch         for (j=0;j<pcbddc->benign_n;j++) PetscCall(VecSetValues(v,1,&p0_lidx_I[j],&zero,INSERT_VALUES));
45739566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(v));
45749566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(v));
45759566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D,i+n_vertices,&v));
457606656605SStefano Zampini       }
45779566063dSJacob Faibussowitsch       PetscCall(VecResetArray(pcbddc->vec1_R));
457806656605SStefano Zampini     }
457906656605SStefano Zampini   }
458080677318SStefano Zampini   if (n_constraints) {
45819566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&local_auxmat2_R));
458280677318SStefano Zampini   }
45839566063dSJacob Faibussowitsch   PetscCall(PetscFree(p0_lidx_I));
458472b8c272SStefano Zampini 
458572b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
458672b8c272SStefano Zampini   if (pcbddc->benign_n) {
458772b8c272SStefano Zampini     Mat               B0_B,B0_BPHI;
458872b8c272SStefano Zampini     IS                is_dummy;
45891683a169SBarry Smith     const PetscScalar *data;
459072b8c272SStefano Zampini     PetscInt          j;
459172b8c272SStefano Zampini 
45929566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy));
45939566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B));
45949566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_dummy));
45959566063dSJacob Faibussowitsch     PetscCall(MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI));
45969566063dSJacob Faibussowitsch     PetscCall(MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI));
45979566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B0_BPHI,&data));
459872b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
459972b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
460072b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
460172b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
460272b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
460372b8c272SStefano Zampini       }
460472b8c272SStefano Zampini     }
46059566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B0_BPHI,&data));
46069566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B0_B));
46079566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B0_BPHI));
460872b8c272SStefano Zampini   }
4609019a44ceSStefano Zampini 
461006656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
46113301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4612ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4613ffd830a3SStefano Zampini     PetscScalar *marray;
461406656605SStefano Zampini 
461506656605SStefano Zampini     if (n_constraints) {
4616ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
461706656605SStefano Zampini 
46189566063dSJacob Faibussowitsch       PetscCall(MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT));
46199566063dSJacob Faibussowitsch       PetscCall(MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT));
46209566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C));
46219566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&S_CCT));
462206656605SStefano Zampini       if (n_vertices) {
4623ffd830a3SStefano Zampini         Mat S_VCT;
462406656605SStefano Zampini 
46259566063dSJacob Faibussowitsch         PetscCall(MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT));
46269566063dSJacob Faibussowitsch         PetscCall(MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V));
46279566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&S_VCT));
462806656605SStefano Zampini       }
46299566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C_CRT));
46305b782168SStefano Zampini     } else {
46319566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V));
463206656605SStefano Zampini     }
463316f15bc4SStefano Zampini     if (n_vertices && n_R) {
4634ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4635ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4636ffd830a3SStefano Zampini       PetscInt       n;
4637ffd830a3SStefano Zampini       PetscBool      flg_row;
463806656605SStefano Zampini 
4639ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
46409566063dSJacob Faibussowitsch       PetscCall(MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR));
46419566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row));
46429566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(A_VR,&av));
46439566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(B_V,&marray));
4644ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4645ffd830a3SStefano Zampini         PetscInt j;
4646ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4647ffd830a3SStefano Zampini       }
46489566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(B_V,&marray));
46499566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row));
46509566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A_VR));
465106656605SStefano Zampini     }
465206656605SStefano Zampini 
4653ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4654abc8f43dSstefano_zampini     if (n_vertices) {
46559566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(B_V,&marray));
4656ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
46579566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec1_R,marray+i*n_R));
46589566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec2_R,work+i*n_R));
46599566063dSJacob Faibussowitsch         PetscCall(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R));
46609566063dSJacob Faibussowitsch         PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
46619566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec1_R));
46629566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec2_R));
466306656605SStefano Zampini       }
46649566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(B_V,&marray));
4665abc8f43dSstefano_zampini     }
46665b782168SStefano Zampini     if (B_C) {
46679566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(B_C,&marray));
4668ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
46699566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R));
46709566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec2_R,work+i*n_R));
46719566063dSJacob Faibussowitsch         PetscCall(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R));
46729566063dSJacob Faibussowitsch         PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
46739566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec1_R));
46749566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec2_R));
467506656605SStefano Zampini       }
46769566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(B_C,&marray));
46775b782168SStefano Zampini     }
467806656605SStefano Zampini     /* coarse basis functions */
467906656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4680ab2d12f3SJunchao Zhang       Vec  v;
468106656605SStefano Zampini 
46829566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(pcbddc->vec1_R,work+i*n_R));
46839566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_B,i,&v));
46849566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
46859566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
468606656605SStefano Zampini       if (i<n_vertices) {
4687ab2d12f3SJunchao Zhang         PetscScalar one = 1.0;
46889566063dSJacob Faibussowitsch         PetscCall(VecSetValues(v,1,&idx_V_B[i],&one,INSERT_VALUES));
46899566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(v));
46909566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(v));
469106656605SStefano Zampini       }
46929566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_B,i,&v));
469306656605SStefano Zampini 
469406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
46959566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_D,i,&v));
46969566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
46979566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
46989566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_D,i,&v));
469906656605SStefano Zampini       }
47009566063dSJacob Faibussowitsch       PetscCall(VecResetArray(pcbddc->vec1_R));
470106656605SStefano Zampini     }
47029566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_V));
47039566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_C));
470406656605SStefano Zampini   }
4705a6e023c1Sstefano_zampini 
4706d62866d3SStefano Zampini   /* free memory */
47079566063dSJacob Faibussowitsch   PetscCall(PetscFree(idx_V_B));
47089566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_VV));
47099566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_CV));
47109566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_VC));
47119566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_CC));
47129566063dSJacob Faibussowitsch   PetscCall(PetscFree(work));
4713d62866d3SStefano Zampini   if (n_vertices) {
47149566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_VR));
4715d62866d3SStefano Zampini   }
4716d62866d3SStefano Zampini   if (n_constraints) {
47179566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C_CR));
4718d62866d3SStefano Zampini   }
47199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0));
47208ead10e4SStefano Zampini 
472188ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
472288ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
472388ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4724d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
472588ebb749SStefano Zampini     Mat         coarse_sub_mat;
472625084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
472788ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
472888ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
472988ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
47308bec7fa6SStefano Zampini     Mat         C_B,CPHI;
47318bec7fa6SStefano Zampini     IS          is_dummy;
47328bec7fa6SStefano Zampini     Vec         mones;
473388ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
473488ebb749SStefano Zampini     PetscReal   real_value;
473588ebb749SStefano Zampini 
4736a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4737a3df083aSStefano Zampini       Mat A;
47389566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignProject(pc,NULL,NULL,&A));
47399566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II));
47409566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB));
47419566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI));
47429566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB));
47439566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A));
4744a3df083aSStefano Zampini     } else {
47459566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II));
47469566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB));
47479566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI));
47489566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB));
4749a3df083aSStefano Zampini     }
47509566063dSJacob Faibussowitsch     PetscCall(MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D));
47519566063dSJacob Faibussowitsch     PetscCall(MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B));
4752ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
47539566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D));
47549566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B));
475588ebb749SStefano Zampini     }
47569566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat));
475788ebb749SStefano Zampini 
47589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
47599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal));
47609566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
4761ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
47629566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47639566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1));
47649566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
47659566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47669566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2));
47679566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
47689566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47699566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3));
47709566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
47719566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47729566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4));
47739566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
477488ebb749SStefano Zampini     } else {
47759566063dSJacob Faibussowitsch       PetscCall(MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1));
47769566063dSJacob Faibussowitsch       PetscCall(MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2));
47779566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47789566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3));
47799566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
47809566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47819566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4));
47829566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
478388ebb749SStefano Zampini     }
47849566063dSJacob Faibussowitsch     PetscCall(MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN));
47859566063dSJacob Faibussowitsch     PetscCall(MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN));
47869566063dSJacob Faibussowitsch     PetscCall(MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN));
47879566063dSJacob Faibussowitsch     PetscCall(MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1));
47884f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4789fc227af8SStefano Zampini       Mat               B0_B,B0_BPHI;
47901683a169SBarry Smith       const PetscScalar *data2;
47911683a169SBarry Smith       PetscScalar       *data;
47924f1b2e48SStefano Zampini       PetscInt          j;
4793d12edf2fSStefano Zampini 
47949566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy));
47959566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B));
47969566063dSJacob Faibussowitsch       PetscCall(MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI));
47979566063dSJacob Faibussowitsch       PetscCall(MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI));
47989566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(TM1,&data));
47999566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B0_BPHI,&data2));
48004f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
48014f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4802d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
48034f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
48044f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
48054f1b2e48SStefano Zampini         }
4806d12edf2fSStefano Zampini       }
48079566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(TM1,&data));
48089566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B0_BPHI,&data2));
48099566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B0_B));
48109566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is_dummy));
48119566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B0_BPHI));
4812d12edf2fSStefano Zampini     }
4813d12edf2fSStefano Zampini #if 0
4814d12edf2fSStefano Zampini   {
4815d12edf2fSStefano Zampini     PetscViewer viewer;
4816d12edf2fSStefano Zampini     char filename[256];
4817ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
48189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer));
48199566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB));
48209566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coarse_sub_mat,"computed"));
48219566063dSJacob Faibussowitsch     PetscCall(MatView(coarse_sub_mat,viewer));
48229566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)TM1,"projected"));
48239566063dSJacob Faibussowitsch     PetscCall(MatView(TM1,viewer));
4824a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
48259566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B"));
48269566063dSJacob Faibussowitsch       PetscCall(MatView(pcbddc->coarse_phi_B,viewer));
482772b8c272SStefano Zampini     }
4828ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
48299566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D"));
48309566063dSJacob Faibussowitsch       PetscCall(MatView(pcbddc->coarse_phi_D,viewer));
4831ffd830a3SStefano Zampini     }
4832ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
48339566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B"));
48349566063dSJacob Faibussowitsch       PetscCall(MatView(pcbddc->coarse_psi_B,viewer));
4835ffd830a3SStefano Zampini     }
483672b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
48379566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D"));
48389566063dSJacob Faibussowitsch       PetscCall(MatView(pcbddc->coarse_psi_D,viewer));
4839ffd830a3SStefano Zampini     }
48409566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcbddc->local_mat,"A"));
48419566063dSJacob Faibussowitsch     PetscCall(MatView(pcbddc->local_mat,viewer));
48429566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C"));
48439566063dSJacob Faibussowitsch     PetscCall(MatView(pcbddc->ConstraintMatrix,viewer));
48449566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcis->is_I_local,"I"));
48459566063dSJacob Faibussowitsch     PetscCall(ISView(pcis->is_I_local,viewer));
48469566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcis->is_B_local,"B"));
48479566063dSJacob Faibussowitsch     PetscCall(ISView(pcis->is_B_local,viewer));
48489566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R"));
48499566063dSJacob Faibussowitsch     PetscCall(ISView(pcbddc->is_R_local,viewer));
48509566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
4851d12edf2fSStefano Zampini   }
4852d12edf2fSStefano Zampini #endif
48539566063dSJacob Faibussowitsch     PetscCall(MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN));
48549566063dSJacob Faibussowitsch     PetscCall(MatNorm(TM1,NORM_FROBENIUS,&real_value));
48559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
485663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,(double)real_value));
48578bec7fa6SStefano Zampini 
48588bec7fa6SStefano Zampini     /* check constraints */
48599566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy));
48609566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B));
48614f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
48629566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI));
4863a00504b5SStefano Zampini     } else {
4864a00504b5SStefano Zampini       PetscScalar *data;
4865a00504b5SStefano Zampini       Mat         tmat;
48669566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B,&data));
48679566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat));
48689566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(pcbddc->coarse_phi_B,&data));
48699566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI));
48709566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&tmat));
4871a00504b5SStefano Zampini     }
48729566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(CPHI,&mones,NULL));
48739566063dSJacob Faibussowitsch     PetscCall(VecSet(mones,-1.0));
48749566063dSJacob Faibussowitsch     PetscCall(MatDiagonalSet(CPHI,mones,ADD_VALUES));
48759566063dSJacob Faibussowitsch     PetscCall(MatNorm(CPHI,NORM_FROBENIUS,&real_value));
487663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,(double)real_value));
4877ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
48789566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI));
48799566063dSJacob Faibussowitsch       PetscCall(VecSet(mones,-1.0));
48809566063dSJacob Faibussowitsch       PetscCall(MatDiagonalSet(CPHI,mones,ADD_VALUES));
48819566063dSJacob Faibussowitsch       PetscCall(MatNorm(CPHI,NORM_FROBENIUS,&real_value));
488263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,(double)real_value));
488388ebb749SStefano Zampini     }
48849566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C_B));
48859566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&CPHI));
48869566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_dummy));
48879566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&mones));
48889566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
48899566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_II));
48909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_BB));
48919566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_IB));
48929566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_BI));
48939566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&TM1));
48949566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&TM2));
48959566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&TM3));
48969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&TM4));
48979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&coarse_phi_D));
48989566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&coarse_phi_B));
4899ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
49009566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&coarse_psi_D));
49019566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&coarse_psi_B));
490288ebb749SStefano Zampini     }
49039566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&coarse_sub_mat));
490488ebb749SStefano Zampini   }
49057ebab0bbSStefano Zampini   /* FINAL CUDA support (we cannot currently mix viennacl and cuda vectors */
49067ebab0bbSStefano Zampini   {
49077ebab0bbSStefano Zampini     PetscBool gpu;
49087ebab0bbSStefano Zampini 
49099566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pcis->vec1_N,VECSEQCUDA,&gpu));
49107ebab0bbSStefano Zampini     if (gpu) {
49117ebab0bbSStefano Zampini       if (pcbddc->local_auxmat1) {
49129566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->local_auxmat1,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat1));
49137ebab0bbSStefano Zampini       }
49147ebab0bbSStefano Zampini       if (pcbddc->local_auxmat2) {
49159566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->local_auxmat2,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat2));
49167ebab0bbSStefano Zampini       }
49177ebab0bbSStefano Zampini       if (pcbddc->coarse_phi_B) {
49189566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->coarse_phi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_B));
49197ebab0bbSStefano Zampini       }
49207ebab0bbSStefano Zampini       if (pcbddc->coarse_phi_D) {
49219566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->coarse_phi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_D));
49227ebab0bbSStefano Zampini       }
49237ebab0bbSStefano Zampini       if (pcbddc->coarse_psi_B) {
49249566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->coarse_psi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_B));
49257ebab0bbSStefano Zampini       }
49267ebab0bbSStefano Zampini       if (pcbddc->coarse_psi_D) {
49279566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->coarse_psi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_D));
49287ebab0bbSStefano Zampini       }
49297ebab0bbSStefano Zampini     }
49307ebab0bbSStefano Zampini   }
49318629588bSStefano Zampini   /* get back data */
49328629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
493388ebb749SStefano Zampini   PetscFunctionReturn(0);
493488ebb749SStefano Zampini }
493588ebb749SStefano Zampini 
49367dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4937aa0d41d4SStefano Zampini {
4938d65f70fdSStefano Zampini   Mat            *work_mat;
4939d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4940d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4941c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4942aa0d41d4SStefano Zampini 
4943aa0d41d4SStefano Zampini   PetscFunctionBegin;
49449566063dSJacob Faibussowitsch   PetscCall(ISSorted(isrow,&rsorted));
49459566063dSJacob Faibussowitsch   PetscCall(ISSorted(iscol,&csorted));
49469566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow,&rsize));
49479566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol,&csize));
4948aa0d41d4SStefano Zampini 
4949d65f70fdSStefano Zampini   if (!rsorted) {
4950906d46d4SStefano Zampini     const PetscInt *idxs;
4951906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4952aa0d41d4SStefano Zampini 
49539566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(rsize,&idxs_perm_r));
49549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(rsize,&idxs_sorted));
4955d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4956d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4957aa0d41d4SStefano Zampini     }
49589566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(isrow,&idxs));
49599566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r));
4960d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4961d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4962aa0d41d4SStefano Zampini     }
49639566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(isrow,&idxs));
49649566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s));
4965d65f70fdSStefano Zampini   } else {
49669566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)isrow));
4967d65f70fdSStefano Zampini     isrow_s = isrow;
4968aa0d41d4SStefano Zampini   }
4969906d46d4SStefano Zampini 
4970d65f70fdSStefano Zampini   if (!csorted) {
4971d65f70fdSStefano Zampini     if (isrow == iscol) {
49729566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)isrow_s));
4973d65f70fdSStefano Zampini       iscol_s = isrow_s;
4974d65f70fdSStefano Zampini     } else {
4975d65f70fdSStefano Zampini       const PetscInt *idxs;
4976d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4977906d46d4SStefano Zampini 
49789566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(csize,&idxs_perm_c));
49799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(csize,&idxs_sorted));
4980d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4981d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4982d65f70fdSStefano Zampini       }
49839566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(iscol,&idxs));
49849566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithPermutation(csize,idxs,idxs_perm_c));
4985d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4986d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4987d65f70fdSStefano Zampini       }
49889566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(iscol,&idxs));
49899566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s));
4990d65f70fdSStefano Zampini     }
4991d65f70fdSStefano Zampini   } else {
49929566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)iscol));
4993d65f70fdSStefano Zampini     iscol_s = iscol;
4994d65f70fdSStefano Zampini   }
4995d65f70fdSStefano Zampini 
49969566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat));
4997d65f70fdSStefano Zampini 
4998d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4999906d46d4SStefano Zampini     Mat      new_mat;
5000d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
5001906d46d4SStefano Zampini 
5002d65f70fdSStefano Zampini     if (!rsorted) {
5003d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
50049566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(rsize,&idxs_r));
5005d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
5006d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
5007906d46d4SStefano Zampini       }
50089566063dSJacob Faibussowitsch       PetscCall(PetscFree(idxs_perm_r));
50099566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r));
5010d65f70fdSStefano Zampini     } else {
50119566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r));
5012906d46d4SStefano Zampini     }
50139566063dSJacob Faibussowitsch     PetscCall(ISSetPermutation(is_perm_r));
5014d65f70fdSStefano Zampini 
5015d65f70fdSStefano Zampini     if (!csorted) {
5016d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
50179566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)is_perm_r));
5018d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
5019d65f70fdSStefano Zampini       } else {
5020d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
502128b400f6SJacob Faibussowitsch         PetscCheck(idxs_perm_c,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
50229566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(csize,&idxs_c));
5023d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
5024d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
5025d65f70fdSStefano Zampini         }
50269566063dSJacob Faibussowitsch         PetscCall(PetscFree(idxs_perm_c));
50279566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c));
5028d65f70fdSStefano Zampini       }
5029d65f70fdSStefano Zampini     } else {
50309566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c));
5031d65f70fdSStefano Zampini     }
50329566063dSJacob Faibussowitsch     PetscCall(ISSetPermutation(is_perm_c));
5033d65f70fdSStefano Zampini 
50349566063dSJacob Faibussowitsch     PetscCall(MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat));
50359566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&work_mat[0]));
5036d65f70fdSStefano Zampini     work_mat[0] = new_mat;
50379566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_perm_r));
50389566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_perm_c));
5039d65f70fdSStefano Zampini   }
5040d65f70fdSStefano Zampini 
50419566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)work_mat[0]));
5042d65f70fdSStefano Zampini   *B = work_mat[0];
50439566063dSJacob Faibussowitsch   PetscCall(MatDestroyMatrices(1,&work_mat));
50449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&isrow_s));
50459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&iscol_s));
5046d65f70fdSStefano Zampini   PetscFunctionReturn(0);
5047d65f70fdSStefano Zampini }
5048d65f70fdSStefano Zampini 
50495e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
5050aa0d41d4SStefano Zampini {
5051aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
50525e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5053022d8d2bSstefano_zampini   Mat            new_mat,lA;
50545e8657edSStefano Zampini   IS             is_local,is_global;
5055d65f70fdSStefano Zampini   PetscInt       local_size;
5056*b94d7dedSBarry Smith   PetscBool      isseqaij,issym,isset;
5057aa0d41d4SStefano Zampini 
5058aa0d41d4SStefano Zampini   PetscFunctionBegin;
50599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_mat));
50609566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,&local_size,NULL));
50619566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local));
50629566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping,is_local,&is_global));
50639566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_local));
50649566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat));
50659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_global));
5066906d46d4SStefano Zampini 
5067906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
5068906d46d4SStefano Zampini     Vec       x,x_change;
5069906d46d4SStefano Zampini     PetscReal error;
5070906d46d4SStefano Zampini 
50719566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change));
50729566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(x,NULL));
50739566063dSJacob Faibussowitsch     PetscCall(MatMult(ChangeOfBasisMatrix,x,x_change));
50749566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD));
50759566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD));
50769566063dSJacob Faibussowitsch     PetscCall(MatMult(new_mat,matis->x,matis->y));
507788428137SStefano Zampini     if (!pcbddc->change_interior) {
507888428137SStefano Zampini       const PetscScalar *x,*y,*v;
507988428137SStefano Zampini       PetscReal         lerror = 0.;
508088428137SStefano Zampini       PetscInt          i;
508188428137SStefano Zampini 
50829566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(matis->x,&x));
50839566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(matis->y,&y));
50849566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(matis->counter,&v));
508588428137SStefano Zampini       for (i=0;i<local_size;i++)
508688428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
508788428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
50889566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(matis->x,&x));
50899566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(matis->y,&y));
50909566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(matis->counter,&v));
50911c2dc1cbSBarry Smith       PetscCall(MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)pc)));
5092637e8532SStefano Zampini       if (error > PETSC_SMALL) {
5093637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
509463a3b9bcSJacob Faibussowitsch           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e",(double)error);
5095637e8532SStefano Zampini         } else {
509663a3b9bcSJacob Faibussowitsch           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e",(double)error);
5097637e8532SStefano Zampini         }
5098637e8532SStefano Zampini       }
509988428137SStefano Zampini     }
51009566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE));
51019566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE));
51029566063dSJacob Faibussowitsch     PetscCall(VecAXPY(x,-1.0,x_change));
51039566063dSJacob Faibussowitsch     PetscCall(VecNorm(x,NORM_INFINITY,&error));
5104637e8532SStefano Zampini     if (error > PETSC_SMALL) {
5105637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
510663a3b9bcSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",(double)error);
5107637e8532SStefano Zampini       } else {
510863a3b9bcSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e",(double)error);
5109637e8532SStefano Zampini       }
5110637e8532SStefano Zampini     }
51119566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&x));
51129566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&x_change));
5113906d46d4SStefano Zampini   }
5114906d46d4SStefano Zampini 
5115022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
51169566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA));
5117022d8d2bSstefano_zampini 
511822d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
51199566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij));
512022d5777bSStefano Zampini   if (isseqaij) {
51219566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
51229566063dSJacob Faibussowitsch     PetscCall(MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat));
5123022d8d2bSstefano_zampini     if (lA) {
5124022d8d2bSstefano_zampini       Mat work;
51259566063dSJacob Faibussowitsch       PetscCall(MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work));
51269566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work));
51279566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&work));
5128022d8d2bSstefano_zampini     }
5129aa0d41d4SStefano Zampini   } else {
5130a00504b5SStefano Zampini     Mat work_mat;
51311cf9b237SStefano Zampini 
51329566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
51339566063dSJacob Faibussowitsch     PetscCall(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat));
51349566063dSJacob Faibussowitsch     PetscCall(MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat));
51359566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&work_mat));
5136022d8d2bSstefano_zampini     if (lA) {
5137022d8d2bSstefano_zampini       Mat work;
51389566063dSJacob Faibussowitsch       PetscCall(MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat));
51399566063dSJacob Faibussowitsch       PetscCall(MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work));
51409566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work));
51419566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&work));
5142022d8d2bSstefano_zampini     }
5143aa0d41d4SStefano Zampini   }
5144*b94d7dedSBarry Smith   PetscCall(MatIsSymmetricKnown(matis->A,&isset,&issym));
5145*b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,issym));
51469566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&new_mat));
5147aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
5148aa0d41d4SStefano Zampini }
5149aa0d41d4SStefano Zampini 
51508ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
5151a64d13efSStefano Zampini {
5152a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
5153a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
5154d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
515553892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
51563a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
51573a50541eSStefano Zampini   PetscInt        vbs,bs;
51586816873aSStefano Zampini   PetscBT         bitmask=NULL;
5159a64d13efSStefano Zampini 
5160a64d13efSStefano Zampini   PetscFunctionBegin;
5161b23d619eSStefano Zampini   /*
5162b23d619eSStefano Zampini     No need to setup local scatters if
5163b23d619eSStefano Zampini       - primal space is unchanged
5164b23d619eSStefano Zampini         AND
5165b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
5166b23d619eSStefano Zampini         AND
5167b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
5168b23d619eSStefano Zampini   */
5169b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
5170f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
5171f4ddd8eeSStefano Zampini   }
5172f4ddd8eeSStefano Zampini   /* destroy old objects */
51739566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->is_R_local));
51749566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcbddc->R_to_B));
51759566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcbddc->R_to_D));
5176a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
5177b371cd4fSStefano Zampini   n_B = pcis->n_B;
5178b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
5179b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
51803a50541eSStefano Zampini 
5181a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
51826816873aSStefano Zampini 
518353892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
5184b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
51859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n-n_vertices,&idx_R_local));
51869566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(pcis->n,&bitmask));
5187a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
51889566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]));
5189a64d13efSStefano Zampini     }
5190a64d13efSStefano Zampini 
5191a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
51924641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
51936816873aSStefano Zampini         idx_R_local[n_R++] = i;
5194a64d13efSStefano Zampini       }
5195a64d13efSStefano Zampini     }
5196df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
5197df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
51986816873aSStefano Zampini 
51999566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local));
52009566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(reuse_solver->is_R,&n_R));
52016816873aSStefano Zampini   }
52023a50541eSStefano Zampini 
52033a50541eSStefano Zampini   /* Block code */
52043a50541eSStefano Zampini   vbs = 1;
52059566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(pcbddc->local_mat,&bs));
52063a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
52073a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
52083a50541eSStefano Zampini     PetscInt  *vary;
5209b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
52109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcis->n/bs,&vary));
52119566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(vary,pcis->n/bs));
5212d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
5213d3df7717SStefano 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 */
52140e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
5215d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
52163a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
52173a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
52183a50541eSStefano Zampini           break;
52193a50541eSStefano Zampini         }
52203a50541eSStefano Zampini       }
52219566063dSJacob Faibussowitsch       PetscCall(PetscFree(vary));
5222d3df7717SStefano Zampini     } else {
5223d3df7717SStefano Zampini       /* Verify directly the R set */
5224d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
5225d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
5226d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
5227d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
5228d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
5229d3df7717SStefano Zampini             break;
5230d3df7717SStefano Zampini           }
5231d3df7717SStefano Zampini         }
5232d3df7717SStefano Zampini       }
5233d3df7717SStefano Zampini     }
52343a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
52353a50541eSStefano Zampini       vbs = bs;
52363a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
52373a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
52383a50541eSStefano Zampini       }
52393a50541eSStefano Zampini     }
52403a50541eSStefano Zampini   }
52419566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local));
5242b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
5243df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
524453892102SStefano Zampini 
52459566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local));
52469566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&reuse_solver->is_R));
52479566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->is_R_local));
5248df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
524953892102SStefano Zampini   } else {
52509566063dSJacob Faibussowitsch     PetscCall(PetscFree(idx_R_local));
525153892102SStefano Zampini   }
5252a64d13efSStefano Zampini 
5253a64d13efSStefano Zampini   /* print some info if requested */
5254a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
52559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
52569566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
52579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
52589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank));
525963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %" PetscInt_FMT ", dirichlet_size = %" PetscInt_FMT ", boundary_size = %" PetscInt_FMT "\n",pcis->n,n_D,n_B));
526063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"r_size = %" PetscInt_FMT ", v_size = %" PetscInt_FMT ", constraints = %" PetscInt_FMT ", local_primal_size = %" PetscInt_FMT "\n",n_R,n_vertices,pcbddc->local_primal_size-n_vertices-pcbddc->benign_n,pcbddc->local_primal_size));
52619566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
5262a64d13efSStefano Zampini   }
5263a64d13efSStefano Zampini 
5264a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
5265b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
52666816873aSStefano Zampini     IS       is_aux1,is_aux2;
52676816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
52686816873aSStefano Zampini 
52699566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local));
52709566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n_B-n_vertices,&aux_array1));
52719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n_B-n_vertices,&aux_array2));
52729566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices));
52734641a718SStefano Zampini     for (i=0; i<n_D; i++) {
52749566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(bitmask,is_indices[i]));
52754641a718SStefano Zampini     }
52769566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices));
5277a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
52784641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
52794641a718SStefano Zampini         aux_array1[j++] = i;
5280a64d13efSStefano Zampini       }
5281a64d13efSStefano Zampini     }
52829566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1));
52839566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices));
5284a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
52854641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
52864641a718SStefano Zampini         aux_array2[j++] = i;
5287a64d13efSStefano Zampini       }
5288a64d13efSStefano Zampini     }
52899566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices));
52909566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2));
52919566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B));
52929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_aux1));
52939566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_aux2));
5294a64d13efSStefano Zampini 
52958eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
52969566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_D,&aux_array1));
5297a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
52984641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
52994641a718SStefano Zampini           aux_array1[j++] = i;
5300a64d13efSStefano Zampini         }
5301a64d13efSStefano Zampini       }
53029566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1));
53039566063dSJacob Faibussowitsch       PetscCall(VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D));
53049566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is_aux1));
5305a64d13efSStefano Zampini     }
53069566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&bitmask));
53079566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local));
5308d62866d3SStefano Zampini   } else {
5309df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
53106816873aSStefano Zampini     IS                 tis;
53116816873aSStefano Zampini     PetscInt           schur_size;
53126816873aSStefano Zampini 
53139566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(reuse_solver->is_B,&schur_size));
53149566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis));
53159566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B));
53169566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&tis));
53176816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
53189566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis));
53199566063dSJacob Faibussowitsch       PetscCall(VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D));
53209566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&tis));
5321d62866d3SStefano Zampini     }
5322d62866d3SStefano Zampini   }
5323a64d13efSStefano Zampini   PetscFunctionReturn(0);
5324a64d13efSStefano Zampini }
5325a64d13efSStefano Zampini 
53266d9e27e4SStefano Zampini static PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B)
532792cccca0SStefano Zampini {
532892cccca0SStefano Zampini   MatNullSpace   NullSpace;
532992cccca0SStefano Zampini   Mat            dmat;
533092cccca0SStefano Zampini   const Vec      *nullvecs;
533192cccca0SStefano Zampini   Vec            v,v2,*nullvecs2;
53326d9e27e4SStefano Zampini   VecScatter     sct = NULL;
5333eb06acf8SStefano Zampini   PetscContainer c;
5334eb06acf8SStefano Zampini   PetscScalar    *ddata;
5335295df10fSStefano Zampini   PetscInt       k,nnsp_size,bsiz,bsiz2,n,N,bs;
533692cccca0SStefano Zampini   PetscBool      nnsp_has_cnst;
533792cccca0SStefano Zampini 
533892cccca0SStefano Zampini   PetscFunctionBegin;
53396d9e27e4SStefano Zampini   if (!is && !B) { /* MATIS */
53406d9e27e4SStefano Zampini     Mat_IS* matis = (Mat_IS*)A->data;
53416d9e27e4SStefano Zampini 
53426d9e27e4SStefano Zampini     if (!B) {
53439566063dSJacob Faibussowitsch       PetscCall(MatISGetLocalMat(A,&B));
53446d9e27e4SStefano Zampini     }
53456d9e27e4SStefano Zampini     sct  = matis->cctx;
53469566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)sct));
53476d9e27e4SStefano Zampini   } else {
53489566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(B,&NullSpace));
534992cccca0SStefano Zampini     if (!NullSpace) {
53509566063dSJacob Faibussowitsch       PetscCall(MatGetNearNullSpace(B,&NullSpace));
535192cccca0SStefano Zampini     }
535292cccca0SStefano Zampini     if (NullSpace) PetscFunctionReturn(0);
53536d9e27e4SStefano Zampini   }
53549566063dSJacob Faibussowitsch   PetscCall(MatGetNullSpace(A,&NullSpace));
535592cccca0SStefano Zampini   if (!NullSpace) {
53569566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(A,&NullSpace));
535792cccca0SStefano Zampini   }
535892cccca0SStefano Zampini   if (!NullSpace) PetscFunctionReturn(0);
53596d9e27e4SStefano Zampini 
53609566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A,&v,NULL));
53619566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(B,&v2,NULL));
53626d9e27e4SStefano Zampini   if (!sct) {
53639566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(v,is,v2,NULL,&sct));
53646d9e27e4SStefano Zampini   }
53659566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceGetVecs(NullSpace,&nnsp_has_cnst,&nnsp_size,(const Vec**)&nullvecs));
5366295df10fSStefano Zampini   bsiz = bsiz2 = nnsp_size+!!nnsp_has_cnst;
53679566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(bsiz,&nullvecs2));
53689566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(v2,&bs));
53699566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v2,&N));
53709566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v2,&n));
53719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n*bsiz,&ddata));
537292cccca0SStefano Zampini   for (k=0;k<nnsp_size;k++) {
53739566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,ddata + n*k,&nullvecs2[k]));
53749566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD));
53759566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD));
537692cccca0SStefano Zampini   }
537792cccca0SStefano Zampini   if (nnsp_has_cnst) {
53789566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,ddata + n*nnsp_size,&nullvecs2[nnsp_size]));
53799566063dSJacob Faibussowitsch     PetscCall(VecSet(nullvecs2[nnsp_size],1.0));
538092cccca0SStefano Zampini   }
53819566063dSJacob Faibussowitsch   PetscCall(PCBDDCOrthonormalizeVecs(&bsiz2,nullvecs2));
53829566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)B),PETSC_FALSE,bsiz2,nullvecs2,&NullSpace));
5383295df10fSStefano Zampini 
53849566063dSJacob Faibussowitsch   PetscCall(MatCreateDense(PetscObjectComm((PetscObject)B),n,PETSC_DECIDE,N,bsiz2,ddata,&dmat));
53859566063dSJacob Faibussowitsch   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B),&c));
53869566063dSJacob Faibussowitsch   PetscCall(PetscContainerSetPointer(c,ddata));
53879566063dSJacob Faibussowitsch   PetscCall(PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault));
53889566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)dmat,"_PBDDC_Null_dmat_arr",(PetscObject)c));
53899566063dSJacob Faibussowitsch   PetscCall(PetscContainerDestroy(&c));
53909566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)NullSpace,"_PBDDC_Null_dmat",(PetscObject)dmat));
53919566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&dmat));
5392eb06acf8SStefano Zampini 
539392cccca0SStefano Zampini   for (k=0;k<bsiz;k++) {
53949566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nullvecs2[k]));
539592cccca0SStefano Zampini   }
53969566063dSJacob Faibussowitsch   PetscCall(PetscFree(nullvecs2));
53979566063dSJacob Faibussowitsch   PetscCall(MatSetNearNullSpace(B,NullSpace));
53989566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&NullSpace));
53999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v));
54009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v2));
54019566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&sct));
540292cccca0SStefano Zampini   PetscFunctionReturn(0);
540392cccca0SStefano Zampini }
5404304d26faSStefano Zampini 
5405684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
5406304d26faSStefano Zampini {
5407304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5408304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5409304d26faSStefano Zampini   PC             pc_temp;
5410304d26faSStefano Zampini   Mat            A_RR;
541192cccca0SStefano Zampini   MatNullSpace   nnsp;
5412f4ddd8eeSStefano Zampini   MatReuse       reuse;
5413304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
5414304d26faSStefano Zampini   PetscReal      value;
541504708bb6SStefano Zampini   PetscInt       n_D,n_R;
5416*b94d7dedSBarry Smith   PetscBool      issbaij,opts,isset,issym;
54170a545947SLisandro Dalcin   void           (*f)(void) = NULL;
5418312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
5419e604994aSStefano Zampini   size_t         len;
5420304d26faSStefano Zampini 
5421304d26faSStefano Zampini   PetscFunctionBegin;
54229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0));
54236d9e27e4SStefano Zampini   /* approximate solver, propagate NearNullSpace if needed */
54246d9e27e4SStefano Zampini   if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) {
54256d9e27e4SStefano Zampini     MatNullSpace gnnsp1,gnnsp2;
54266d9e27e4SStefano Zampini     PetscBool    lhas,ghas;
54276d9e27e4SStefano Zampini 
54289566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pcbddc->local_mat,&nnsp));
54299566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->pmat,&gnnsp1));
54309566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(pc->pmat,&gnnsp2));
54316d9e27e4SStefano Zampini     lhas = nnsp ? PETSC_TRUE : PETSC_FALSE;
54321c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&lhas,&ghas,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
54336d9e27e4SStefano Zampini     if (!ghas && (gnnsp1 || gnnsp2)) {
54349566063dSJacob Faibussowitsch       PetscCall(MatNullSpacePropagateAny_Private(pc->pmat,NULL,NULL));
54356d9e27e4SStefano Zampini     }
54366d9e27e4SStefano Zampini   }
54376d9e27e4SStefano Zampini 
5438e604994aSStefano Zampini   /* compute prefixes */
54399566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(dir_prefix,""));
54409566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(neu_prefix,""));
5441e604994aSStefano Zampini   if (!pcbddc->current_level) {
54429566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,sizeof(dir_prefix)));
54439566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,sizeof(neu_prefix)));
54449566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix)));
54459566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix)));
5446e604994aSStefano Zampini   } else {
54479566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level)));
54489566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(((PetscObject)pc)->prefix,&len));
5449e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
5450312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5451312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
5452a126751eSBarry Smith     /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */
54539566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1));
54549566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1));
54559566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix)));
54569566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix)));
54579566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(dir_prefix,str_level,sizeof(dir_prefix)));
54589566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(neu_prefix,str_level,sizeof(neu_prefix)));
5459e604994aSStefano Zampini   }
5460e604994aSStefano Zampini 
5461304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
5462684f6988SStefano Zampini   if (dirichlet) {
5463d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5464450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
54657827d75bSBarry Smith       PetscCheck(sub_schurs && sub_schurs->reuse_solver,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
5466450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
5467a3df083aSStefano Zampini         Mat    A_IIn;
5468a3df083aSStefano Zampini 
54699566063dSJacob Faibussowitsch         PetscCall(PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn));
54709566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&pcis->A_II));
5471a3df083aSStefano Zampini         pcis->A_II = A_IIn;
5472a3df083aSStefano Zampini       }
5473450f8f5eSStefano Zampini     }
5474*b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pcbddc->local_mat,&isset,&issym));
5475*b94d7dedSBarry Smith     if (isset) PetscCall(MatSetOption(pcis->A_II,MAT_SYMMETRIC,issym));
5476*b94d7dedSBarry Smith 
5477ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
5478964fefecSStefano Zampini     n_D  = pcis->n - pcis->n_B;
547992cccca0SStefano Zampini     opts = PETSC_FALSE;
5480304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
548192cccca0SStefano Zampini       opts = PETSC_TRUE;
54829566063dSJacob Faibussowitsch       PetscCall(KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D));
54839566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1));
5484304d26faSStefano Zampini       /* default */
54859566063dSJacob Faibussowitsch       PetscCall(KSPSetType(pcbddc->ksp_D,KSPPREONLY));
54869566063dSJacob Faibussowitsch       PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix));
54879566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)pcis->pA_II,MATSEQSBAIJ,&issbaij));
54889566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->ksp_D,&pc_temp));
54899577ea80SStefano Zampini       if (issbaij) {
54909566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc_temp,PCCHOLESKY));
54919577ea80SStefano Zampini       } else {
54929566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc_temp,PCLU));
54939577ea80SStefano Zampini       }
54949566063dSJacob Faibussowitsch       PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_D,pc->erroriffailure));
549592cccca0SStefano Zampini     }
54969566063dSJacob Faibussowitsch     PetscCall(MatSetOptionsPrefix(pcis->pA_II,((PetscObject)pcbddc->ksp_D)->prefix));
54979566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->pA_II));
5498304d26faSStefano Zampini     /* Allow user's customization */
54991baa6e33SBarry Smith     if (opts) PetscCall(KSPSetFromOptions(pcbddc->ksp_D));
55009566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pcis->pA_II,&nnsp));
55016d9e27e4SStefano Zampini     if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */
55029566063dSJacob Faibussowitsch       PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcis->is_I_local,pcis->pA_II));
550392cccca0SStefano Zampini     }
55049566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pcis->pA_II,&nnsp));
55059566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcbddc->ksp_D,&pc_temp));
55069566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f));
550792cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5508cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5509cd18cfedSStefano Zampini       const PetscInt *idxs;
5510cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5511cd18cfedSStefano Zampini 
55129566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcis->is_I_local,&nl));
55139566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcis->is_I_local,&idxs));
55149566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl*cdim,&scoords));
5515cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5516cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5517cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5518cd18cfedSStefano Zampini         }
5519cd18cfedSStefano Zampini       }
55209566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcis->is_I_local,&idxs));
55219566063dSJacob Faibussowitsch       PetscCall(PCSetCoordinates(pc_temp,cdim,nl,scoords));
55229566063dSJacob Faibussowitsch       PetscCall(PetscFree(scoords));
5523cd18cfedSStefano Zampini     }
5524b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5525df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5526d62866d3SStefano Zampini 
55279566063dSJacob Faibussowitsch       PetscCall(KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver));
5528d5574798SStefano Zampini     }
552992cccca0SStefano Zampini 
5530304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5531304d26faSStefano Zampini     if (!n_D) {
55329566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->ksp_D,&pc_temp));
55339566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,PCNONE));
5534304d26faSStefano Zampini     }
55359566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcbddc->ksp_D));
5536304d26faSStefano Zampini     /* set ksp_D into pcis data */
55379566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->ksp_D));
55389566063dSJacob Faibussowitsch     PetscCall(KSPDestroy(&pcis->ksp_D));
5539304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5540684f6988SStefano Zampini   }
5541304d26faSStefano Zampini 
5542304d26faSStefano Zampini   /* NEUMANN PROBLEM */
55430a545947SLisandro Dalcin   A_RR = NULL;
5544684f6988SStefano Zampini   if (neumann) {
5545d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
554604708bb6SStefano Zampini     PetscInt        ibs,mbs;
5547*b94d7dedSBarry Smith     PetscBool       issbaij, reuse_neumann_solver,isset,issym;
554804708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
55490aa714b2SStefano Zampini 
55500aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
55510aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
55520aa714b2SStefano Zampini       IS iP;
55530aa714b2SStefano Zampini 
55540aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
55559566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP));
55560aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
55570aa714b2SStefano Zampini     }
5558f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
55599566063dSJacob Faibussowitsch     PetscCall(ISGetSize(pcbddc->is_R_local,&n_R));
5560f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5561f4ddd8eeSStefano Zampini       PetscInt nn_R;
55629566063dSJacob Faibussowitsch       PetscCall(KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR));
55639566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A_RR));
55649566063dSJacob Faibussowitsch       PetscCall(MatGetSize(A_RR,&nn_R,NULL));
5565f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
55669566063dSJacob Faibussowitsch         PetscCall(KSPReset(pcbddc->ksp_R));
55679566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RR));
5568f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5569f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5570727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
55719566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&A_RR));
5572f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5573f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5574f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5575f4ddd8eeSStefano Zampini         }
5576f4ddd8eeSStefano Zampini       }
5577f4ddd8eeSStefano Zampini       /* last check */
5578d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
55799566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RR));
5580f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5581f4ddd8eeSStefano Zampini       }
5582f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5583f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5584f4ddd8eeSStefano Zampini     }
5585365a3a41SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection
5586365a3a41SStefano Zampini        TODO: Get Rid of these conversions */
55879566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pcbddc->local_mat,&mbs));
55889566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(pcbddc->is_R_local,&ibs));
55899566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij));
559004708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
559104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
55929566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&pcbddc->local_mat));
55939566063dSJacob Faibussowitsch         PetscCall(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat));
5594af732b37SStefano Zampini       } else {
55959566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat));
55966816873aSStefano Zampini       }
559704708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
559804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
55999566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&pcbddc->local_mat));
56009566063dSJacob Faibussowitsch         PetscCall(MatConvert(matis->A,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat));
560104708bb6SStefano Zampini       } else {
56029566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->local_mat,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat));
560304708bb6SStefano Zampini       }
560404708bb6SStefano Zampini     }
5605a00504b5SStefano Zampini     /* extract A_RR */
56060aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5607a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5608a00504b5SStefano Zampini 
5609a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
56109566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RR));
5611a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
56129566063dSJacob Faibussowitsch           PetscCall(PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR));
561316e386b8SStefano Zampini         } else {
56149566063dSJacob Faibussowitsch           PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR));
5615a00504b5SStefano Zampini         }
5616a00504b5SStefano Zampini       } else {
56179566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RR));
56189566063dSJacob Faibussowitsch         PetscCall(PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL));
56199566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A_RR));
5620a00504b5SStefano Zampini       }
5621a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
56229566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR));
562316e386b8SStefano Zampini     }
5624*b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pcbddc->local_mat,&isset,&issym));
5625*b94d7dedSBarry Smith     if (isset) PetscCall(MatSetOption(A_RR,MAT_SYMMETRIC,issym));
562692cccca0SStefano Zampini     opts = PETSC_FALSE;
5627f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
562892cccca0SStefano Zampini       opts = PETSC_TRUE;
56299566063dSJacob Faibussowitsch       PetscCall(KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R));
56309566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1));
5631304d26faSStefano Zampini       /* default */
56329566063dSJacob Faibussowitsch       PetscCall(KSPSetType(pcbddc->ksp_R,KSPPREONLY));
56339566063dSJacob Faibussowitsch       PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix));
56349566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->ksp_R,&pc_temp));
56359566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij));
56369577ea80SStefano Zampini       if (issbaij) {
56379566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc_temp,PCCHOLESKY));
56389577ea80SStefano Zampini       } else {
56399566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc_temp,PCLU));
56409577ea80SStefano Zampini       }
56419566063dSJacob Faibussowitsch       PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_R,pc->erroriffailure));
564292cccca0SStefano Zampini     }
56439566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR));
56449566063dSJacob Faibussowitsch     PetscCall(MatSetOptionsPrefix(A_RR,((PetscObject)pcbddc->ksp_R)->prefix));
564592cccca0SStefano Zampini     if (opts) { /* Allow user's customization once */
56469566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(pcbddc->ksp_R));
564792cccca0SStefano Zampini     }
56489566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(A_RR,&nnsp));
56496d9e27e4SStefano Zampini     if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */
56509566063dSJacob Faibussowitsch       PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcbddc->is_R_local,A_RR));
565192cccca0SStefano Zampini     }
56529566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(A_RR,&nnsp));
56539566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcbddc->ksp_R,&pc_temp));
56549566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f));
565592cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5656cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5657cd18cfedSStefano Zampini       const PetscInt *idxs;
5658cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5659cd18cfedSStefano Zampini 
56609566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->is_R_local,&nl));
56619566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->is_R_local,&idxs));
56629566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl*cdim,&scoords));
5663cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5664cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5665cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5666cd18cfedSStefano Zampini         }
5667cd18cfedSStefano Zampini       }
56689566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->is_R_local,&idxs));
56699566063dSJacob Faibussowitsch       PetscCall(PCSetCoordinates(pc_temp,cdim,nl,scoords));
56709566063dSJacob Faibussowitsch       PetscCall(PetscFree(scoords));
5671cd18cfedSStefano Zampini     }
567292cccca0SStefano Zampini 
5673304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5674304d26faSStefano Zampini     if (!n_R) {
56759566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->ksp_R,&pc_temp));
56769566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,PCNONE));
5677304d26faSStefano Zampini     }
5678df4d28bfSStefano Zampini     /* Reuse solver if it is present */
56790aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5680df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5681d62866d3SStefano Zampini 
56829566063dSJacob Faibussowitsch       PetscCall(KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver));
5683d62866d3SStefano Zampini     }
56849566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcbddc->ksp_R));
5685684f6988SStefano Zampini   }
5686304d26faSStefano Zampini 
5687684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
56889566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
56899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
56909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
5691684f6988SStefano Zampini   }
56929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0));
5693c7017625SStefano Zampini 
5694c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
5695c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
56969566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE));
5697c7017625SStefano Zampini   }
5698c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
56999566063dSJacob Faibussowitsch     PetscCall(PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]));
5700c7017625SStefano Zampini   }
5701c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
57029566063dSJacob Faibussowitsch     PetscCall(PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]));
5703c7017625SStefano Zampini   }
5704c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5705c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5706684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
57079566063dSJacob Faibussowitsch       PetscCall(VecSetRandom(pcis->vec1_D,NULL));
57089566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D));
57099566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D));
57109566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
57119566063dSJacob Faibussowitsch       PetscCall(VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D));
57129566063dSJacob Faibussowitsch       PetscCall(VecNorm(pcis->vec1_D,NORM_INFINITY,&value));
571363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Dirichlet solve (%s) = % 1.14e \n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_D))->prefix,(double)value));
57149566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
5715304d26faSStefano Zampini     }
5716684f6988SStefano Zampini     if (neumann) { /* Neumann */
57179566063dSJacob Faibussowitsch       PetscCall(VecSetRandom(pcbddc->vec1_R,NULL));
57189566063dSJacob Faibussowitsch       PetscCall(MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R));
57199566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R));
57209566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
57219566063dSJacob Faibussowitsch       PetscCall(VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R));
57229566063dSJacob Faibussowitsch       PetscCall(VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value));
572363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Neumann solve (%s) = % 1.14e\n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_R))->prefix,(double)value));
57249566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
5725304d26faSStefano Zampini     }
5726684f6988SStefano Zampini   }
57275cbda25cSStefano Zampini   /* free Neumann problem's matrix */
57289566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A_RR));
5729304d26faSStefano Zampini   PetscFunctionReturn(0);
5730304d26faSStefano Zampini }
5731304d26faSStefano Zampini 
573280677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5733674ae819SStefano Zampini {
5734674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5735be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5736b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
5737674ae819SStefano Zampini 
5738674ae819SStefano Zampini   PetscFunctionBegin;
5739b334f244SStefano Zampini   if (!reuse_solver) {
57409566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->vec1_R,0.));
574120c7b377SStefano Zampini   }
574280677318SStefano Zampini   if (!pcbddc->switch_static) {
574380677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
57449566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C));
57459566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B));
574620c7b377SStefano Zampini     }
5747b334f244SStefano Zampini     if (!reuse_solver) {
57489566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57499566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
575020c7b377SStefano Zampini     } else {
5751df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5752be83ff47SStefano Zampini 
57539566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD));
57549566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD));
575520c7b377SStefano Zampini     }
5756be83ff47SStefano Zampini   } else {
57579566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57589566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57599566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57609566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
576180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
57629566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C));
57639566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B));
57649566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57659566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
5766674ae819SStefano Zampini     }
5767674ae819SStefano Zampini   }
57689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1],pc,0,0,0));
5769b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
577080677318SStefano Zampini     if (applytranspose) {
57719566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R));
577280677318SStefano Zampini     } else {
57739566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R));
577480677318SStefano Zampini     }
57759566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec1_R));
5776be83ff47SStefano Zampini   } else {
5777df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5778be83ff47SStefano Zampini 
5779be83ff47SStefano Zampini     if (applytranspose) {
57809566063dSJacob Faibussowitsch       PetscCall(MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B));
5781be83ff47SStefano Zampini     } else {
57829566063dSJacob Faibussowitsch       PetscCall(MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B));
5783be83ff47SStefano Zampini     }
5784be83ff47SStefano Zampini   }
57859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1],pc,0,0,0));
57869566063dSJacob Faibussowitsch   PetscCall(VecSet(inout_B,0.));
578780677318SStefano Zampini   if (!pcbddc->switch_static) {
5788b334f244SStefano Zampini     if (!reuse_solver) {
57899566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
57909566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
5791be83ff47SStefano Zampini     } else {
5792df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5793be83ff47SStefano Zampini 
57949566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE));
57959566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE));
5796be83ff47SStefano Zampini     }
579780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
57989566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C));
57999566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B));
580080677318SStefano Zampini     }
580180677318SStefano Zampini   } else {
58029566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
58039566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
58049566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD));
58059566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD));
580680677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
58079566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C));
58089566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R));
580980677318SStefano Zampini     }
58109566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
58119566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
58129566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD));
58139566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD));
5814674ae819SStefano Zampini   }
5815674ae819SStefano Zampini   PetscFunctionReturn(0);
5816674ae819SStefano Zampini }
5817674ae819SStefano Zampini 
5818dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5819dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5820674ae819SStefano Zampini {
5821674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5822674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5823674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5824674ae819SStefano Zampini 
5825674ae819SStefano Zampini   PetscFunctionBegin;
5826dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
58274fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5828dc359a40SStefano Zampini     if (applytranspose) {
58299566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P));
58309566063dSJacob Faibussowitsch       if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P));
5831dc359a40SStefano Zampini     } else {
58329566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P));
58339566063dSJacob Faibussowitsch       if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P));
583415aaf578SStefano Zampini     }
58354fee134fSStefano Zampini   } else {
58369566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->vec1_P,zero));
58374fee134fSStefano Zampini   }
5838efc2fbd9SStefano Zampini 
5839efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
58404f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5841efc2fbd9SStefano Zampini     PetscScalar *array;
58424f1b2e48SStefano Zampini     PetscInt    j;
5843efc2fbd9SStefano Zampini 
58449566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcbddc->vec1_P,&array));
58454f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
58469566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcbddc->vec1_P,&array));
5847efc2fbd9SStefano Zampini   }
5848efc2fbd9SStefano Zampini 
584912edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
58509566063dSJacob Faibussowitsch   PetscCall(VecSet(pcbddc->coarse_vec,zero));
58519566063dSJacob Faibussowitsch   PetscCall(PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD));
58529566063dSJacob Faibussowitsch   PetscCall(PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD));
585312edc857SStefano Zampini 
58549f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
585512edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
585651694757SStefano Zampini     Mat          coarse_mat;
5857964fefecSStefano Zampini     Vec          rhs,sol;
585851694757SStefano Zampini     MatNullSpace nullsp;
585927b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5860964fefecSStefano Zampini 
586127b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
586227b6a85dSStefano Zampini       PC        coarse_pc;
586327b6a85dSStefano Zampini 
58649566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc));
58659566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc));
586627b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
586727b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
586827b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
586927b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
58703bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
587127b6a85dSStefano Zampini       }
587227b6a85dSStefano Zampini     }
58739566063dSJacob Faibussowitsch     PetscCall(KSPGetRhs(pcbddc->coarse_ksp,&rhs));
58749566063dSJacob Faibussowitsch     PetscCall(KSPGetSolution(pcbddc->coarse_ksp,&sol));
58759566063dSJacob Faibussowitsch     PetscCall(KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL));
587612edc857SStefano Zampini     if (applytranspose) {
587728b400f6SJacob Faibussowitsch       PetscCheck(!pcbddc->benign_apply_coarse_only,PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
58789566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0));
58799566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol));
58809566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0));
58819566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->coarse_ksp,pc,sol));
58829566063dSJacob Faibussowitsch       PetscCall(MatGetTransposeNullSpace(coarse_mat,&nullsp));
58831baa6e33SBarry Smith       if (nullsp) PetscCall(MatNullSpaceRemove(nullsp,sol));
58842701bc32SStefano Zampini     } else {
58859566063dSJacob Faibussowitsch       PetscCall(MatGetNullSpace(coarse_mat,&nullsp));
58861f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
58872701bc32SStefano Zampini         PC        coarse_pc;
58882701bc32SStefano Zampini 
58891baa6e33SBarry Smith         if (nullsp) PetscCall(MatNullSpaceRemove(nullsp,rhs));
58909566063dSJacob Faibussowitsch         PetscCall(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc));
58919566063dSJacob Faibussowitsch         PetscCall(PCPreSolve(coarse_pc,pcbddc->coarse_ksp));
58929566063dSJacob Faibussowitsch         PetscCall(PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol));
58939566063dSJacob Faibussowitsch         PetscCall(PCPostSolve(coarse_pc,pcbddc->coarse_ksp));
589412edc857SStefano Zampini       } else {
58959566063dSJacob Faibussowitsch         PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0));
58969566063dSJacob Faibussowitsch         PetscCall(KSPSolve(pcbddc->coarse_ksp,rhs,sol));
58979566063dSJacob Faibussowitsch         PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0));
58989566063dSJacob Faibussowitsch         PetscCall(KSPCheckSolve(pcbddc->coarse_ksp,pc,sol));
58991baa6e33SBarry Smith         if (nullsp) PetscCall(MatNullSpaceRemove(nullsp,sol));
590012edc857SStefano Zampini       }
59012701bc32SStefano Zampini     }
59021d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
590327b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
590427b6a85dSStefano Zampini       PC        coarse_pc;
590527b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
590627b6a85dSStefano Zampini 
59079566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc));
590827b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
590927b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
59103bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
591127b6a85dSStefano Zampini     }
591212edc857SStefano Zampini   }
5913674ae819SStefano Zampini 
5914674ae819SStefano Zampini   /* Local solution on R nodes */
59154fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
59169566063dSJacob Faibussowitsch     PetscCall(PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose));
59179f00e9b4SStefano Zampini   }
59189f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
59199566063dSJacob Faibussowitsch   PetscCall(PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE));
59209566063dSJacob Faibussowitsch   PetscCall(PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE));
5921674ae819SStefano Zampini 
59224fee134fSStefano Zampini   /* Sum contributions from the two levels */
59234fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5924dc359a40SStefano Zampini     if (applytranspose) {
59259566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B));
59269566063dSJacob Faibussowitsch       if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D));
5927dc359a40SStefano Zampini     } else {
59289566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B));
59299566063dSJacob Faibussowitsch       if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D));
5930dc359a40SStefano Zampini     }
5931efc2fbd9SStefano Zampini     /* store p0 */
59324f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5933efc2fbd9SStefano Zampini       PetscScalar *array;
59344f1b2e48SStefano Zampini       PetscInt    j;
5935efc2fbd9SStefano Zampini 
59369566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcbddc->vec1_P,&array));
59374f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
59389566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcbddc->vec1_P,&array));
5939efc2fbd9SStefano Zampini     }
59404fee134fSStefano Zampini   } else { /* expand the coarse solution */
59414fee134fSStefano Zampini     if (applytranspose) {
59429566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B));
59434fee134fSStefano Zampini     } else {
59449566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B));
59454fee134fSStefano Zampini     }
59464fee134fSStefano Zampini   }
5947674ae819SStefano Zampini   PetscFunctionReturn(0);
5948674ae819SStefano Zampini }
5949674ae819SStefano Zampini 
595012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5951674ae819SStefano Zampini {
5952674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
595312edc857SStefano Zampini   Vec               from,to;
59547ebab0bbSStefano Zampini   const PetscScalar *array;
5955674ae819SStefano Zampini 
5956674ae819SStefano Zampini   PetscFunctionBegin;
595712edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
595812edc857SStefano Zampini     from = pcbddc->coarse_vec;
595912edc857SStefano Zampini     to = pcbddc->vec1_P;
596012edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
596112edc857SStefano Zampini       Vec tvec;
596258da7f69SStefano Zampini 
59639566063dSJacob Faibussowitsch       PetscCall(KSPGetRhs(pcbddc->coarse_ksp,&tvec));
59649566063dSJacob Faibussowitsch       PetscCall(VecResetArray(tvec));
59659566063dSJacob Faibussowitsch       PetscCall(KSPGetSolution(pcbddc->coarse_ksp,&tvec));
59669566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tvec,&array));
59679566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(from,array));
59689566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tvec,&array));
596912edc857SStefano Zampini     }
597012edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
597112edc857SStefano Zampini     from = pcbddc->vec1_P;
597212edc857SStefano Zampini     to = pcbddc->coarse_vec;
597312edc857SStefano Zampini   }
59749566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode));
5975674ae819SStefano Zampini   PetscFunctionReturn(0);
5976674ae819SStefano Zampini }
5977674ae819SStefano Zampini 
597812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5979674ae819SStefano Zampini {
5980674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
598112edc857SStefano Zampini   Vec               from,to;
59827ebab0bbSStefano Zampini   const PetscScalar *array;
5983674ae819SStefano Zampini 
5984674ae819SStefano Zampini   PetscFunctionBegin;
598512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
598612edc857SStefano Zampini     from = pcbddc->coarse_vec;
598712edc857SStefano Zampini     to = pcbddc->vec1_P;
598812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
598912edc857SStefano Zampini     from = pcbddc->vec1_P;
599012edc857SStefano Zampini     to = pcbddc->coarse_vec;
599112edc857SStefano Zampini   }
59929566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode));
599312edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
599412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
599512edc857SStefano Zampini       Vec tvec;
599658da7f69SStefano Zampini 
59979566063dSJacob Faibussowitsch       PetscCall(KSPGetRhs(pcbddc->coarse_ksp,&tvec));
59989566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(to,&array));
59999566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(tvec,array));
60009566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(to,&array));
600158da7f69SStefano Zampini     }
600258da7f69SStefano Zampini   } else {
600358da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
60049566063dSJacob Faibussowitsch      PetscCall(VecResetArray(from));
600512edc857SStefano Zampini     }
600612edc857SStefano Zampini   }
6007674ae819SStefano Zampini   PetscFunctionReturn(0);
6008674ae819SStefano Zampini }
6009674ae819SStefano Zampini 
6010674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
6011674ae819SStefano Zampini {
6012674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
6013674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
6014674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
6015984c4197SStefano Zampini   /* one and zero */
6016984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
6017984c4197SStefano Zampini   /* space to store constraints and their local indices */
60189162d606SStefano Zampini   PetscScalar       *constraints_data;
60199162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
60209162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
60219162d606SStefano Zampini   PetscInt          *constraints_n;
6022984c4197SStefano Zampini   /* iterators */
6023b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
6024984c4197SStefano Zampini   /* BLAS integers */
6025e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
6026e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
6027c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
6028727cdba6SStefano Zampini   /* reuse */
60290e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
60300e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
6031984c4197SStefano Zampini   /* change of basis */
6032b3d85658SStefano Zampini   PetscBool         qr_needed;
60339162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
6034984c4197SStefano Zampini   /* auxiliary stuff */
603564efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
60368a0068c3SStefano Zampini   PetscInt          ncc;
6037984c4197SStefano Zampini   /* some quantities */
603845a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
6039a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
604057715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
6041984c4197SStefano Zampini 
6042674ae819SStefano Zampini   PetscFunctionBegin;
604357715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
60448e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
60459566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix));
60469566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->ConstraintMatrix));
60479566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->switch_static_change));
6048088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
6049088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
60500e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
60519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult));
60529566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc));
60539566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc));
60549566063dSJacob Faibussowitsch   PetscCall(PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult));
60559566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->primal_indices_local_idxs));
6056cf5a6209SStefano Zampini 
6057cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
60589162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
6059cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
6060cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
6061cf5a6209SStefano Zampini     Vec          *localnearnullsp;
6062cf5a6209SStefano Zampini     PetscScalar  *array;
606332fe681dSStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size,o_nf,o_ne;
6064cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
6065674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
6066b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
6067674ae819SStefano Zampini     PetscScalar  *work;
6068674ae819SStefano Zampini     PetscReal    *singular_vals;
6069674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6070674ae819SStefano Zampini     PetscReal    *rwork;
6071674ae819SStefano Zampini #endif
607255080a34SStefano Zampini     PetscScalar  *temp_basis = NULL,*correlation_mat = NULL;
6073964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
6074964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
607555080a34SStefano Zampini     PetscBool    use_pod = PETSC_FALSE;
6076674ae819SStefano Zampini 
607755080a34SStefano Zampini     /* MKL SVD with same input gives different results on different processes! */
6078b88df2e7SBarry Smith #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL_LIBS)
607955080a34SStefano Zampini     use_pod = PETSC_TRUE;
608055080a34SStefano Zampini #endif
6081674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
60829566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices));
608332fe681dSStefano Zampini     o_nf = n_ISForFaces;
608432fe681dSStefano Zampini     o_ne = n_ISForEdges;
608532fe681dSStefano Zampini     n_vertices = 0;
608632fe681dSStefano Zampini     if (ISForVertices) PetscCall(ISGetSize(ISForVertices,&n_vertices));
6087e4d548c7SStefano Zampini     /* print some info */
60885c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
6089e4d548c7SStefano Zampini 
609032fe681dSStefano Zampini       if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
60919566063dSJacob Faibussowitsch       PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer));
60929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
60939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n"));
609432fe681dSStefano Zampini       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n",PetscGlobalRank,n_vertices,pcbddc->use_vertices));
609563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges));
609663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces));
60979566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
60989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
6099e4d548c7SStefano Zampini     }
6100e4d548c7SStefano Zampini 
610132fe681dSStefano Zampini     if (!pcbddc->use_vertices) n_vertices = 0;
610232fe681dSStefano Zampini     if (!pcbddc->use_edges) n_ISForEdges = 0;
610332fe681dSStefano Zampini     if (!pcbddc->use_faces) n_ISForFaces = 0;
610470022509SStefano Zampini 
6105674ae819SStefano Zampini     /* check if near null space is attached to global mat */
61066d9e27e4SStefano Zampini     if (pcbddc->use_nnsp) {
61079566063dSJacob Faibussowitsch       PetscCall(MatGetNearNullSpace(pc->pmat,&nearnullsp));
61086d9e27e4SStefano Zampini     } else nearnullsp = NULL;
61096d9e27e4SStefano Zampini 
6110674ae819SStefano Zampini     if (nearnullsp) {
61119566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs));
6112f4ddd8eeSStefano Zampini       /* remove any stored info */
61139566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace));
61149566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddc->onearnullvecs_state));
6115f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
61169566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)nearnullsp));
6117f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
61189566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state));
6119f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
61209566063dSJacob Faibussowitsch         PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]));
6121f4ddd8eeSStefano Zampini       }
6122984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
6123984c4197SStefano Zampini       nnsp_size = 0;
6124674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
6125674ae819SStefano Zampini     }
6126984c4197SStefano Zampini     /* get max number of constraints on a single cc */
6127984c4197SStefano Zampini     max_constraints = nnsp_size;
6128984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
6129984c4197SStefano Zampini 
6130674ae819SStefano Zampini     /*
6131674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
61329162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
61339162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
61349162d606SStefano Zampini          There can be multiple constraints per connected component
6135674ae819SStefano Zampini                                                                                                                                                            */
61369162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
61379566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n));
61389162d606SStefano Zampini 
61399162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
61409162d606SStefano Zampini     total_counts *= max_constraints;
6141674ae819SStefano Zampini     total_counts += n_vertices;
61429566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(total_counts,&change_basis));
61439162d606SStefano Zampini 
6144674ae819SStefano Zampini     total_counts = 0;
6145674ae819SStefano Zampini     max_size_of_constraint = 0;
6146674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
61479162d606SStefano Zampini       IS used_is;
6148674ae819SStefano Zampini       if (i<n_ISForEdges) {
61499162d606SStefano Zampini         used_is = ISForEdges[i];
6150674ae819SStefano Zampini       } else {
61519162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
6152674ae819SStefano Zampini       }
61539566063dSJacob Faibussowitsch       PetscCall(ISGetSize(used_is,&j));
6154674ae819SStefano Zampini       total_counts += j;
6155674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
6156674ae819SStefano Zampini     }
61579566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(total_counts*max_constraints+n_vertices,&constraints_data,total_counts+n_vertices,&constraints_idxs,total_counts+n_vertices,&constraints_idxs_B));
61589162d606SStefano Zampini 
6159984c4197SStefano Zampini     /* get local part of global near null space vectors */
61609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnsp_size,&localnearnullsp));
6161984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
61629566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(pcis->vec1_N,&localnearnullsp[k]));
61639566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD));
61649566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD));
6165984c4197SStefano Zampini     }
6166674ae819SStefano Zampini 
6167242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
6168242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
6169a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
6170242a89d7SStefano Zampini 
6171984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
6172a773dcb8SStefano Zampini     if (!skip_lapack) {
6173674ae819SStefano Zampini       PetscScalar temp_work;
6174911cabfeSStefano Zampini 
617555080a34SStefano Zampini       if (use_pod) {
6176984c4197SStefano Zampini         /* Proper Orthogonal Decomposition (POD) using the snapshot method */
61779566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(max_constraints*max_constraints,&correlation_mat));
61789566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(max_constraints,&singular_vals));
61799566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis));
6180674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
61819566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(3*max_constraints,&rwork));
6182674ae819SStefano Zampini #endif
6183674ae819SStefano Zampini         /* now we evaluate the optimal workspace using query with lwork=-1 */
61849566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(max_constraints,&Blas_N));
61859566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(max_constraints,&Blas_LDA));
6186674ae819SStefano Zampini         lwork = -1;
61879566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6188674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6189c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
6190674ae819SStefano Zampini #else
6191c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
6192674ae819SStefano Zampini #endif
61939566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPop());
619428b400f6SJacob Faibussowitsch         PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
619555080a34SStefano Zampini       } else {
619655080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
6197674ae819SStefano Zampini         /* SVD */
6198674ae819SStefano Zampini         PetscInt max_n,min_n;
6199674ae819SStefano Zampini         max_n = max_size_of_constraint;
6200984c4197SStefano Zampini         min_n = max_constraints;
6201984c4197SStefano Zampini         if (max_size_of_constraint < max_constraints) {
6202674ae819SStefano Zampini           min_n = max_size_of_constraint;
6203984c4197SStefano Zampini           max_n = max_constraints;
6204674ae819SStefano Zampini         }
62059566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(min_n,&singular_vals));
6206674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
62079566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(5*min_n,&rwork));
6208674ae819SStefano Zampini #endif
6209674ae819SStefano Zampini         /* now we evaluate the optimal workspace using query with lwork=-1 */
6210674ae819SStefano Zampini         lwork = -1;
62119566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(max_n,&Blas_M));
62129566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(min_n,&Blas_N));
62139566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(max_n,&Blas_LDA));
62149566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6215674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
62169162d606SStefano 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));
6217674ae819SStefano Zampini #else
62189162d606SStefano 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));
6219674ae819SStefano Zampini #endif
62209566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPop());
622128b400f6SJacob Faibussowitsch         PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
622255080a34SStefano Zampini #else
622355080a34SStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen");
6224984c4197SStefano Zampini #endif /* on missing GESVD */
622555080a34SStefano Zampini       }
6226674ae819SStefano Zampini       /* Allocate optimal workspace */
62279566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork));
62289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(lwork,&work));
6229674ae819SStefano Zampini     }
6230674ae819SStefano Zampini     /* Now we can loop on constraining sets */
6231674ae819SStefano Zampini     total_counts = 0;
62329162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
62339162d606SStefano Zampini     constraints_data_ptr[0] = 0;
6234674ae819SStefano Zampini     /* vertices */
62359162d606SStefano Zampini     if (n_vertices) {
62369566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(ISForVertices,(const PetscInt**)&is_indices));
62379566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(constraints_idxs,is_indices,n_vertices));
6238674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
62399162d606SStefano Zampini         constraints_n[total_counts] = 1;
62409162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
62419162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
62429162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
6243674ae819SStefano Zampini         total_counts++;
6244674ae819SStefano Zampini       }
62459566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices));
6246674ae819SStefano Zampini     }
6247984c4197SStefano Zampini 
6248674ae819SStefano Zampini     /* edges and faces */
62499162d606SStefano Zampini     total_counts_cc = total_counts;
6250911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
62519162d606SStefano Zampini       IS        used_is;
62529162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
62539162d606SStefano Zampini 
6254911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
62559162d606SStefano Zampini         used_is = ISForEdges[ncc];
6256984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
6257674ae819SStefano Zampini       } else {
62589162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
6259984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
6260674ae819SStefano Zampini       }
6261674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
62629162d606SStefano Zampini 
62639566063dSJacob Faibussowitsch       PetscCall(ISGetSize(used_is,&size_of_constraint));
626432fe681dSStefano Zampini       if (!size_of_constraint) continue;
62659566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(used_is,(const PetscInt**)&is_indices));
6266984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
6267984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
6268674ae819SStefano Zampini       if (nnsp_has_cnst) {
62695b08dc53SStefano Zampini         PetscScalar quad_value;
62709162d606SStefano Zampini 
62719566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint));
62729162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
62739162d606SStefano Zampini 
6274a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
6275674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
6276a773dcb8SStefano Zampini         } else {
6277a773dcb8SStefano Zampini           quad_value = 1.0;
6278a773dcb8SStefano Zampini         }
6279674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
62809162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
6281674ae819SStefano Zampini         }
62829162d606SStefano Zampini         temp_constraints++;
6283674ae819SStefano Zampini         total_counts++;
6284674ae819SStefano Zampini       }
6285674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
6286984c4197SStefano Zampini         PetscReal real_value;
62879162d606SStefano Zampini         PetscScalar *ptr_to_data;
62889162d606SStefano Zampini 
62899566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array));
62909162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
6291674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
62929162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
6293674ae819SStefano Zampini         }
62949566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array));
6295984c4197SStefano Zampini         /* check if array is null on the connected component */
62969566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
62979162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
629857715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
6299674ae819SStefano Zampini           temp_constraints++;
6300674ae819SStefano Zampini           total_counts++;
63019162d606SStefano Zampini           if (!idxs_copied) {
63029566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint));
63039162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
6304674ae819SStefano Zampini           }
6305674ae819SStefano Zampini         }
63069162d606SStefano Zampini       }
63079566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(used_is,(const PetscInt**)&is_indices));
630845a1bb75SStefano Zampini       valid_constraints = temp_constraints;
6309eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
6310a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
63119162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
63129162d606SStefano Zampini 
63139162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
63149566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
63159162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
6316a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
63179162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
6318a773dcb8SStefano Zampini         } else { /* perform SVD */
63199162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6320674ae819SStefano Zampini 
632155080a34SStefano Zampini           if (use_pod) {
6322984c4197SStefano Zampini             /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
6323984c4197SStefano Zampini                POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
6324984c4197SStefano Zampini                -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
6325984c4197SStefano Zampini                   the constraints basis will differ (by a complex factor with absolute value equal to 1)
6326984c4197SStefano Zampini                   from that computed using LAPACKgesvd
6327984c4197SStefano Zampini                -> This is due to a different computation of eigenvectors in LAPACKheev
6328984c4197SStefano Zampini                -> The quality of the POD-computed basis will be the same */
63299566063dSJacob Faibussowitsch             PetscCall(PetscArrayzero(correlation_mat,temp_constraints*temp_constraints));
6330674ae819SStefano Zampini             /* Store upper triangular part of correlation matrix */
63319566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
63329566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6333674ae819SStefano Zampini             for (j=0;j<temp_constraints;j++) {
6334674ae819SStefano Zampini               for (k=0;k<j+1;k++) {
63359162d606SStefano 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));
6336674ae819SStefano Zampini               }
6337674ae819SStefano Zampini             }
6338e310c8b4SStefano Zampini             /* compute eigenvalues and eigenvectors of correlation matrix */
63399566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_N));
63409566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_LDA));
6341674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6342c8244a33SStefano Zampini             PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
6343674ae819SStefano Zampini #else
6344c8244a33SStefano Zampini             PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
6345674ae819SStefano Zampini #endif
63469566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPop());
634728b400f6SJacob Faibussowitsch             PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
6348984c4197SStefano Zampini             /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
6349674ae819SStefano Zampini             j = 0;
635087b3baaaSStefano Zampini             while (j < temp_constraints && singular_vals[j]/singular_vals[temp_constraints-1] < tol) j++;
6351674ae819SStefano Zampini             total_counts = total_counts-j;
635245a1bb75SStefano Zampini             valid_constraints = temp_constraints-j;
6353e310c8b4SStefano Zampini             /* scale and copy POD basis into used quadrature memory */
63549566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
63559566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_N));
63569566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_K));
63579566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
63589566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_LDB));
63599566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDC));
6360674ae819SStefano Zampini             if (j<temp_constraints) {
6361984c4197SStefano Zampini               PetscInt ii;
6362984c4197SStefano Zampini               for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
63639566063dSJacob Faibussowitsch               PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
63649162d606SStefano 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));
63659566063dSJacob Faibussowitsch               PetscCall(PetscFPTrapPop());
6366984c4197SStefano Zampini               for (k=0;k<temp_constraints-j;k++) {
6367674ae819SStefano Zampini                 for (ii=0;ii<size_of_constraint;ii++) {
63689162d606SStefano 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];
6369674ae819SStefano Zampini                 }
6370674ae819SStefano Zampini               }
6371674ae819SStefano Zampini             }
637255080a34SStefano Zampini           } else {
637355080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
63749566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
63759566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_N));
63769566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
63779566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6378674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
63799162d606SStefano 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));
6380674ae819SStefano Zampini #else
63819162d606SStefano 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));
6382674ae819SStefano Zampini #endif
638328b400f6SJacob Faibussowitsch             PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
63849566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPop());
6385984c4197SStefano Zampini             /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
6386e310c8b4SStefano Zampini             k = temp_constraints;
6387e310c8b4SStefano Zampini             if (k > size_of_constraint) k = size_of_constraint;
6388674ae819SStefano Zampini             j = 0;
638987b3baaaSStefano Zampini             while (j < k && singular_vals[k-j-1]/singular_vals[0] < tol) j++;
639045a1bb75SStefano Zampini             valid_constraints = k-j;
6391911cabfeSStefano Zampini             total_counts = total_counts-temp_constraints+valid_constraints;
639255080a34SStefano Zampini #else
639355080a34SStefano Zampini             SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen");
6394984c4197SStefano Zampini #endif /* on missing GESVD */
6395674ae819SStefano Zampini           }
6396a773dcb8SStefano Zampini         }
639755080a34SStefano Zampini       }
63989162d606SStefano Zampini       /* update pointers information */
63999162d606SStefano Zampini       if (valid_constraints) {
64009162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
64019162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
64029162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
64039162d606SStefano Zampini         /* set change_of_basis flag */
640445a1bb75SStefano Zampini         if (boolforchange) {
6405b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
64069162d606SStefano Zampini         }
6407b3d85658SStefano Zampini         total_counts_cc++;
640845a1bb75SStefano Zampini       }
640945a1bb75SStefano Zampini     }
6410984c4197SStefano Zampini     /* free workspace */
64118f1c130eSStefano Zampini     if (!skip_lapack) {
64129566063dSJacob Faibussowitsch       PetscCall(PetscFree(work));
6413984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
64149566063dSJacob Faibussowitsch       PetscCall(PetscFree(rwork));
6415984c4197SStefano Zampini #endif
64169566063dSJacob Faibussowitsch       PetscCall(PetscFree(singular_vals));
64179566063dSJacob Faibussowitsch       PetscCall(PetscFree(correlation_mat));
64189566063dSJacob Faibussowitsch       PetscCall(PetscFree(temp_basis));
6419984c4197SStefano Zampini     }
6420984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
64219566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&localnearnullsp[k]));
6422984c4197SStefano Zampini     }
64239566063dSJacob Faibussowitsch     PetscCall(PetscFree(localnearnullsp));
6424cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
642532fe681dSStefano Zampini     PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,&o_nf,&ISForFaces,&o_ne,&ISForEdges,&ISForVertices));
642608122e43SStefano Zampini   } else {
642708122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6428984c4197SStefano Zampini 
642908122e43SStefano Zampini     total_counts = 0;
643008122e43SStefano Zampini     n_vertices = 0;
6431d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
64329566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(sub_schurs->is_vertices,&n_vertices));
643308122e43SStefano Zampini     }
643408122e43SStefano Zampini     max_constraints = 0;
64359162d606SStefano Zampini     total_counts_cc = 0;
643608122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
643708122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
64389162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
643908122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
644008122e43SStefano Zampini     }
64419162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
64429162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
64439162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
64449162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
644574d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
64469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(total_counts_cc,&constraints_n));
64479162d606SStefano Zampini     total_counts_cc = 0;
64489162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
64499162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
64509162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
645108122e43SStefano Zampini       }
645208122e43SStefano Zampini     }
645308122e43SStefano Zampini 
64548bec7fa6SStefano Zampini     max_size_of_constraint = 0;
64559162d606SStefano 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]);
64569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B));
645708122e43SStefano Zampini     /* Change of basis */
64589566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(total_counts_cc,&change_basis));
645908122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
646008122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
646108122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
64629566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(change_basis,i+n_vertices));
646308122e43SStefano Zampini         }
646408122e43SStefano Zampini       }
646508122e43SStefano Zampini     }
646608122e43SStefano Zampini   }
6467984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
64689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs));
646908122e43SStefano Zampini 
64709162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
647132fe681dSStefano Zampini   if (pcbddc->use_change_of_basis) {
64729566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B));
647363a3b9bcSJacob Faibussowitsch     PetscCheck(i == constraints_idxs_ptr[total_counts_cc],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for constraints indices %" PetscInt_FMT " != %" PetscInt_FMT,constraints_idxs_ptr[total_counts_cc],i);
647432fe681dSStefano Zampini   }
6475674ae819SStefano Zampini 
6476674ae819SStefano Zampini   /* Create constraint matrix */
64779566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix));
64789566063dSJacob Faibussowitsch   PetscCall(MatSetType(pcbddc->ConstraintMatrix,MATAIJ));
64799566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n));
6480984c4197SStefano Zampini 
6481984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6482a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
64835a52fde0SStefano Zampini   qr_needed = pcbddc->use_qr_single;
64849566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(total_counts_cc,&qr_needed_idx));
6485984c4197SStefano Zampini   total_primal_vertices=0;
6486b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
64879162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
64889162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
648972b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
64909162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6491b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
649264efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
64939162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
64949162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6495a717540cSStefano Zampini       }
6496b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
649791af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6498a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6499a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6500a717540cSStefano Zampini       }
6501fa434743SStefano Zampini     } else {
6502b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6503fa434743SStefano Zampini     }
6504a717540cSStefano Zampini   }
6505b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6506b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6507674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
65089566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs));
65099566063dSJacob Faibussowitsch   PetscCall(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));
65109566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices));
65110e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6512984c4197SStefano Zampini 
6513984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
651474d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
65159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pcbddc->local_primal_size,&nnz));
6516984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
651774d5cdf7SStefano Zampini 
6518984c4197SStefano Zampini   j = total_primal_vertices;
651974d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6520b3d85658SStefano Zampini   cum = total_primal_vertices;
65219162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
65224641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6523b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6524b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6525b3d85658SStefano Zampini       cum++;
65269162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
652774d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
652874d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
652974d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
653074d5cdf7SStefano Zampini       }
65319162d606SStefano Zampini       j += constraints_n[i];
6532674ae819SStefano Zampini     }
6533674ae819SStefano Zampini   }
65349566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz));
65359566063dSJacob Faibussowitsch   PetscCall(MatSetOption(pcbddc->ConstraintMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
65369566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
6537088faed8SStefano Zampini 
6538674ae819SStefano Zampini   /* set values in constraint matrix */
6539984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
65409566063dSJacob Faibussowitsch     PetscCall(MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES));
6541674ae819SStefano Zampini   }
6542984c4197SStefano Zampini   total_counts = total_primal_vertices;
65439162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
65444641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
65459162d606SStefano Zampini       PetscInt *cols;
65469162d606SStefano Zampini 
65479162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
65489162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
65499162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
65509162d606SStefano Zampini         PetscInt    row = total_counts+k;
65519162d606SStefano Zampini         PetscScalar *vals;
65529162d606SStefano Zampini 
65539162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
65549566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES));
65559162d606SStefano Zampini       }
65569162d606SStefano Zampini       total_counts += constraints_n[i];
6557674ae819SStefano Zampini     }
6558674ae819SStefano Zampini   }
6559674ae819SStefano Zampini   /* assembling */
65609566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY));
65619566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY));
65629566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(pcbddc->ConstraintMatrix,(PetscObject)pc,"-pc_bddc_constraint_mat_view"));
6563088faed8SStefano Zampini 
6564674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6565674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6566026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6567984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6568984c4197SStefano Zampini     /* working stuff for GEQRF */
65695a52fde0SStefano Zampini     PetscScalar  *qr_basis = NULL,*qr_tau = NULL,*qr_work = NULL,lqr_work_t;
6570984c4197SStefano Zampini     PetscBLASInt lqr_work;
6571984c4197SStefano Zampini     /* working stuff for UNGQR */
65723c377650SSatish Balay     PetscScalar  *gqr_work = NULL,lgqr_work_t=0.0;
6573984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6574984c4197SStefano Zampini     /* working stuff for TRTRS */
65755a52fde0SStefano Zampini     PetscScalar  *trs_rhs = NULL;
65763f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6577984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6578984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6579984c4197SStefano Zampini     PetscScalar  *start_vals;
6580984c4197SStefano Zampini     /* working stuff for values insertion */
65814641a718SStefano Zampini     PetscBT      is_primal;
658264efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6583906d46d4SStefano Zampini     /* matrix sizes */
6584906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6585906d46d4SStefano Zampini     /* temporary change of basis */
6586906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6587cf5a6209SStefano Zampini     /* extra space for debugging */
65885a52fde0SStefano Zampini     PetscScalar  *dbg_work = NULL;
6589984c4197SStefano Zampini 
65909566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix));
65919566063dSJacob Faibussowitsch     PetscCall(MatSetType(localChangeOfBasisMatrix,MATAIJ));
65929566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n));
6593906d46d4SStefano Zampini     /* nonzeros for local mat */
65949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n,&nnz));
65951dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6596bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
65971dd7afcfSStefano Zampini     } else {
65981dd7afcfSStefano Zampini       const PetscInt *ii;
65991dd7afcfSStefano Zampini       PetscInt       n;
66001dd7afcfSStefano Zampini       PetscBool      flg_row;
66019566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row));
66021dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
66039566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row));
66041dd7afcfSStefano Zampini     }
66059162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6606a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
66079162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6608a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
66099162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6610a717540cSStefano Zampini         } else {
66119162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
66129162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6613a717540cSStefano Zampini         }
6614a717540cSStefano Zampini       }
6615a717540cSStefano Zampini     }
66169566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz));
66179566063dSJacob Faibussowitsch     PetscCall(MatSetOption(localChangeOfBasisMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
66189566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
66191dd7afcfSStefano Zampini     /* Set interior change in the matrix */
66201dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6621bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
66229566063dSJacob Faibussowitsch         PetscCall(MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES));
6623a717540cSStefano Zampini       }
66241dd7afcfSStefano Zampini     } else {
66251dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
66261dd7afcfSStefano Zampini       PetscScalar    *aa;
66271dd7afcfSStefano Zampini       PetscInt       n;
66281dd7afcfSStefano Zampini       PetscBool      flg_row;
66299566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row));
66309566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(pcbddc->benign_change,&aa));
66311dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
66329566063dSJacob Faibussowitsch         PetscCall(MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES));
66331dd7afcfSStefano Zampini       }
66349566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(pcbddc->benign_change,&aa));
66359566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row));
66361dd7afcfSStefano Zampini     }
6637a717540cSStefano Zampini 
6638a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
66399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n"));
66409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank));
6641a717540cSStefano Zampini     }
6642a717540cSStefano Zampini 
6643a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6644a717540cSStefano Zampini     /*
6645a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6646a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6647a717540cSStefano Zampini 
66487c625d9fSStefano Zampini        Basic blocks of change of basis matrix T computed:
6649a717540cSStefano Zampini 
66507c625d9fSStefano Zampini           - By using the following block transformation if there is only a primal dof on the cc (and -pc_bddc_use_qr_single is not specified)
6651a6b551f4SStefano Zampini 
6652a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6653a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6654a717540cSStefano Zampini             |              ...                        |
6655a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6656a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6657a717540cSStefano Zampini 
6658a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6659a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6660a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6661a6b551f4SStefano Zampini 
6662a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6663a717540cSStefano Zampini     */
66645a52fde0SStefano Zampini     if (qr_needed && max_size_of_constraint) {
6665984c4197SStefano Zampini       /* space to store Q */
66669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis));
66674e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
66689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(max_constraints,&qr_tau));
6669984c4197SStefano Zampini       /* first we issue queries for optimal work */
66709566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_M));
66719566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_constraints,&Blas_N));
66729566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_LDA));
6673984c4197SStefano Zampini       lqr_work = -1;
66743f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
667528b400f6SJacob Faibussowitsch       PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
66769566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work));
66779566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work));
6678984c4197SStefano Zampini       lgqr_work = -1;
66799566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_M));
66809566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_N));
66819566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_constraints,&Blas_K));
66829566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_LDA));
66833f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6684c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
668528b400f6SJacob Faibussowitsch       PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
66869566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work));
66879566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work));
6688984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
66899566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(max_constraints*max_constraints,&trs_rhs));
6690a717540cSStefano Zampini       /* allocating workspace for check */
6691a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
66929566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work));
6693a717540cSStefano Zampini       }
6694a717540cSStefano Zampini     }
6695984c4197SStefano Zampini     /* array to store whether a node is primal or not */
66969566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(pcis->n_B,&is_primal));
66979566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B));
66989566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B));
669963a3b9bcSJacob Faibussowitsch     PetscCheck(i == total_primal_vertices,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %" PetscInt_FMT " != %" PetscInt_FMT,total_primal_vertices,i);
670039e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
67019566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(is_primal,aux_primal_numbering_B[i]));
670239e2fb2aSStefano Zampini     }
67039566063dSJacob Faibussowitsch     PetscCall(PetscFree(aux_primal_numbering_B));
6704984c4197SStefano Zampini 
6705a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
67069162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
67079162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
67084641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6709984c4197SStefano Zampini         /* get constraint info */
67109162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6711984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6712984c4197SStefano Zampini 
6713984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
671463a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraints %" PetscInt_FMT ": %" PetscInt_FMT " need a change of basis (size %" PetscInt_FMT ")\n",total_counts,primal_dofs,size_of_constraint));
6715674ae819SStefano Zampini         }
6716984c4197SStefano Zampini 
6717fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6718a717540cSStefano Zampini 
6719a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6720a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
67219566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs));
6722a717540cSStefano Zampini           }
6723984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
67249566063dSJacob Faibussowitsch           PetscCall(PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs));
6725984c4197SStefano Zampini 
6726984c4197SStefano Zampini           /* compute QR decomposition of constraints */
67279566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
67289566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_N));
67299566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
67309566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
67313f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
673228b400f6SJacob Faibussowitsch           PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
67339566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
6734984c4197SStefano Zampini 
6735a5b23f4aSJose E. Roman           /* explicitly compute R^-T */
67369566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(trs_rhs,primal_dofs*primal_dofs));
6737984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
67389566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_N));
67399566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_NRHS));
67409566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
67419566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_LDB));
67429566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
67433f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
674428b400f6SJacob Faibussowitsch           PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
67459566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
6746984c4197SStefano Zampini 
6747a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */
67489566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
67499566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
67509566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_K));
67519566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
67529566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6753c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
675428b400f6SJacob Faibussowitsch           PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
67559566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
6756984c4197SStefano Zampini 
6757984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6758984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6759984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
67609566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
67619566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_N));
67629566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_K));
67639566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
67649566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_LDB));
67659566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDC));
67669566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
67679162d606SStefano 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));
67689566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
67699566063dSJacob Faibussowitsch           PetscCall(PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs));
6770984c4197SStefano Zampini 
6771984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
67729162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6773984c4197SStefano Zampini           /* insert cols for primal dofs */
6774984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6775984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
67769162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
67779566063dSJacob Faibussowitsch             PetscCall(MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES));
6778984c4197SStefano Zampini           }
6779984c4197SStefano Zampini           /* insert cols for dual dofs */
6780984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
67819162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6782984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
67839162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
67849566063dSJacob Faibussowitsch               PetscCall(MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES));
6785984c4197SStefano Zampini               j++;
6786674ae819SStefano Zampini             }
6787674ae819SStefano Zampini           }
6788984c4197SStefano Zampini 
6789984c4197SStefano Zampini           /* check change of basis */
6790984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6791984c4197SStefano Zampini             PetscInt   ii,jj;
6792984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
67939566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(primal_dofs,&Blas_M));
67949566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
67959566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_K));
67969566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
67979566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDB));
67989566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(primal_dofs,&Blas_LDC));
67999566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6800cf5a6209SStefano 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));
68019566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPop());
6802984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6803984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6804cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6805c068d9bbSLisandro 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;
6806674ae819SStefano Zampini               }
6807674ae819SStefano Zampini             }
6808984c4197SStefano Zampini             if (!valid_qr) {
68099566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n"));
6810984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6811984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6812cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
681363a3b9bcSJacob Faibussowitsch                     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %" PetscInt_FMT " is not orthogonal to constraint %" PetscInt_FMT " (%1.14e)!\n",jj,ii,(double)PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii])));
6814674ae819SStefano Zampini                   }
6815c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
681663a3b9bcSJacob Faibussowitsch                     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %" PetscInt_FMT " is not unitary w.r.t constraint %" PetscInt_FMT " (%1.14e)!\n",jj,ii,(double)PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii])));
6817984c4197SStefano Zampini                   }
6818984c4197SStefano Zampini                 }
6819984c4197SStefano Zampini               }
6820674ae819SStefano Zampini             } else {
68219566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n"));
6822674ae819SStefano Zampini             }
6823674ae819SStefano Zampini           }
6824a717540cSStefano Zampini         } else { /* simple transformation block */
6825a717540cSStefano Zampini           PetscInt    row,col;
6826a6b551f4SStefano Zampini           PetscScalar val,norm;
6827a6b551f4SStefano Zampini 
68289566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
68299162d606SStefano 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));
6830a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
68319162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
68329162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6833bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
68349162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
68359566063dSJacob Faibussowitsch               PetscCall(MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES));
68369566063dSJacob Faibussowitsch               PetscCall(MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES));
6837a717540cSStefano Zampini             } else {
6838a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
68399162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6840a717540cSStefano Zampini                 if (row != col) {
68419162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6842a717540cSStefano Zampini                 } else {
68439162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6844a717540cSStefano Zampini                 }
68459566063dSJacob Faibussowitsch                 PetscCall(MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES));
6846a717540cSStefano Zampini               }
6847a717540cSStefano Zampini             }
6848a717540cSStefano Zampini           }
684998a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
68509566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n"));
6851a717540cSStefano Zampini           }
6852674ae819SStefano Zampini         }
6853984c4197SStefano Zampini       } else {
6854984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
685563a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %" PetscInt_FMT " does not need a change of basis (size %" PetscInt_FMT ")\n",total_counts,size_of_constraint));
6856674ae819SStefano Zampini         }
6857674ae819SStefano Zampini       }
6858674ae819SStefano Zampini     }
6859a717540cSStefano Zampini 
6860a717540cSStefano Zampini     /* free workspace */
6861a717540cSStefano Zampini     if (qr_needed) {
68621baa6e33SBarry Smith       if (pcbddc->dbg_flag) PetscCall(PetscFree(dbg_work));
68639566063dSJacob Faibussowitsch       PetscCall(PetscFree(trs_rhs));
68649566063dSJacob Faibussowitsch       PetscCall(PetscFree(qr_tau));
68659566063dSJacob Faibussowitsch       PetscCall(PetscFree(qr_work));
68669566063dSJacob Faibussowitsch       PetscCall(PetscFree(gqr_work));
68679566063dSJacob Faibussowitsch       PetscCall(PetscFree(qr_basis));
6868674ae819SStefano Zampini     }
68699566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&is_primal));
68709566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY));
68719566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY));
6872906d46d4SStefano Zampini 
6873906d46d4SStefano Zampini     /* assembling of global change of variable */
687488c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6875bbb9e6c6SStefano Zampini       Mat      tmat;
687616f15bc4SStefano Zampini       PetscInt bs;
687716f15bc4SStefano Zampini 
68789566063dSJacob Faibussowitsch       PetscCall(VecGetSize(pcis->vec1_global,&global_size));
68799566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(pcis->vec1_global,&local_size));
68809566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat));
68819566063dSJacob Faibussowitsch       PetscCall(MatISSetLocalMat(tmat,localChangeOfBasisMatrix));
68829566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY));
68839566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY));
68849566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix));
68859566063dSJacob Faibussowitsch       PetscCall(MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ));
68869566063dSJacob Faibussowitsch       PetscCall(MatGetBlockSize(pc->pmat,&bs));
68879566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs));
68889566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size));
68899566063dSJacob Faibussowitsch       PetscCall(MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE));
68909566063dSJacob Faibussowitsch       PetscCall(MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix));
68919566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&tmat));
68929566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global,0.0));
68939566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_N,1.0));
68949566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
68959566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
68969566063dSJacob Faibussowitsch       PetscCall(VecReciprocal(pcis->vec1_global));
68979566063dSJacob Faibussowitsch       PetscCall(MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL));
689888c03ad3SStefano Zampini 
6899906d46d4SStefano Zampini       /* check */
6900906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6901906d46d4SStefano Zampini         PetscReal error;
6902906d46d4SStefano Zampini         Vec       x,x_change;
6903906d46d4SStefano Zampini 
69049566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(pcis->vec1_global,&x));
69059566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(pcis->vec1_global,&x_change));
69069566063dSJacob Faibussowitsch         PetscCall(VecSetRandom(x,NULL));
69079566063dSJacob Faibussowitsch         PetscCall(VecCopy(x,pcis->vec1_global));
69089566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
69099566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
69109566063dSJacob Faibussowitsch         PetscCall(MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N));
69119566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE));
69129566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE));
69139566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change));
69149566063dSJacob Faibussowitsch         PetscCall(VecAXPY(x,-1.0,x_change));
69159566063dSJacob Faibussowitsch         PetscCall(VecNorm(x,NORM_INFINITY,&error));
6916637e8532SStefano Zampini         if (error > PETSC_SMALL) {
691763a3b9bcSJacob Faibussowitsch           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",(double)error);
6918637e8532SStefano Zampini         }
69199566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&x));
69209566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&x_change));
6921906d46d4SStefano Zampini       }
6922b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6923b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6924b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6925bf3a8328SStefano Zampini 
692608401ef6SPierre Jolivet         PetscCheck(!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");
6927b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6928ac632422SStefano Zampini           Mat                    S_new,tmat;
6929bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6930bbb9e6c6SStefano Zampini 
69319566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N));
69329566063dSJacob Faibussowitsch           PetscCall(MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat));
6933bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6934bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6935bf3a8328SStefano Zampini             IS                     is_V;
69369566063dSJacob Faibussowitsch             PetscCall(ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V));
69379566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall));
69389566063dSJacob Faibussowitsch             PetscCall(ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall));
69399566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingDestroy(&NtoSall));
69409566063dSJacob Faibussowitsch             PetscCall(ISDestroy(&is_V));
6941bf3a8328SStefano Zampini           }
69429566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&is_all_N));
69439566063dSJacob Faibussowitsch           PetscCall(MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new));
69449566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&sub_schurs->S_Ej_all));
69459566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)S_new));
6946bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6947bf3a8328SStefano Zampini             const PetscScalar *array;
6948bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6949bf3a8328SStefano Zampini             PetscInt          i,n_V;
6950bf3a8328SStefano Zampini 
69519566063dSJacob Faibussowitsch             PetscCall(MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL));
69529566063dSJacob Faibussowitsch             PetscCall(ISGetLocalSize(is_V_Sall,&n_V));
69539566063dSJacob Faibussowitsch             PetscCall(ISGetIndices(is_V_Sall,&idxs_V));
69549566063dSJacob Faibussowitsch             PetscCall(ISGetIndices(sub_schurs->is_Ej_all,&idxs_all));
69559566063dSJacob Faibussowitsch             PetscCall(VecGetArrayRead(pcis->D,&array));
6956b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6957b087196eSStefano Zampini               PetscScalar val;
6958b087196eSStefano Zampini               PetscInt    idx;
6959b087196eSStefano Zampini 
6960b087196eSStefano Zampini               idx = idxs_V[i];
6961b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
69629566063dSJacob Faibussowitsch               PetscCall(MatSetValue(S_new,idx,idx,val,INSERT_VALUES));
6963b087196eSStefano Zampini             }
69649566063dSJacob Faibussowitsch             PetscCall(MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY));
69659566063dSJacob Faibussowitsch             PetscCall(MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY));
69669566063dSJacob Faibussowitsch             PetscCall(VecRestoreArrayRead(pcis->D,&array));
69679566063dSJacob Faibussowitsch             PetscCall(ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all));
69689566063dSJacob Faibussowitsch             PetscCall(ISRestoreIndices(is_V_Sall,&idxs_V));
6969bf3a8328SStefano Zampini           }
6970ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
69719566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&S_new));
6972ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
69739566063dSJacob Faibussowitsch             PetscCall(MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new));
69749566063dSJacob Faibussowitsch             PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_all));
69759566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)S_new));
69761baa6e33SBarry Smith             if (pcbddc->deluxe_zerorows) PetscCall(MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL));
6977ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
69789566063dSJacob Faibussowitsch             PetscCall(MatDestroy(&S_new));
6979ac632422SStefano Zampini           }
69809566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&is_V_Sall));
69819566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&tmat));
6982b96c3477SStefano Zampini         }
6983c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6984b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6985c9db6a07SStefano Zampini           PetscInt i;
6986c9db6a07SStefano Zampini 
6987c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
69889566063dSJacob Faibussowitsch             PetscCall(KSPDestroy(&sub_schurs->change[i]));
6989c9db6a07SStefano Zampini           }
69909566063dSJacob Faibussowitsch           PetscCall(PetscFree(sub_schurs->change));
6991c9db6a07SStefano Zampini         }
6992b96c3477SStefano Zampini       }
699316909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
699416909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
699516909a7fSStefano Zampini       } else {
69969566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&localChangeOfBasisMatrix));
699716909a7fSStefano Zampini       }
69981dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
699927b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
700072b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
70019566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->ConstraintMatrix));
700272b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
700372b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
700472b8c272SStefano Zampini     }
70051dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
700627b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
70079566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix));
7008b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
7009906d46d4SStefano Zampini     } else {
70101dd7afcfSStefano Zampini       Mat benign_global = NULL;
701127b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
70121dd7afcfSStefano Zampini         Mat M;
70131dd7afcfSStefano Zampini 
70149e9b7b1fSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
70159566063dSJacob Faibussowitsch         PetscCall(VecCopy(matis->counter,pcis->vec1_N));
70169566063dSJacob Faibussowitsch         PetscCall(VecReciprocal(pcis->vec1_N));
70179566063dSJacob Faibussowitsch         PetscCall(MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&benign_global));
70189e9b7b1fSStefano Zampini         if (pcbddc->benign_change) {
70199566063dSJacob Faibussowitsch           PetscCall(MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M));
70209566063dSJacob Faibussowitsch           PetscCall(MatDiagonalScale(M,pcis->vec1_N,NULL));
7021906d46d4SStefano Zampini         } else {
70229566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&M));
70239566063dSJacob Faibussowitsch           PetscCall(MatDiagonalSet(M,pcis->vec1_N,INSERT_VALUES));
7024906d46d4SStefano Zampini         }
70259566063dSJacob Faibussowitsch         PetscCall(MatISSetLocalMat(benign_global,M));
70269566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&M));
70279566063dSJacob Faibussowitsch         PetscCall(MatAssemblyBegin(benign_global,MAT_FINAL_ASSEMBLY));
70289566063dSJacob Faibussowitsch         PetscCall(MatAssemblyEnd(benign_global,MAT_FINAL_ASSEMBLY));
70291dd7afcfSStefano Zampini       }
70301dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
70319566063dSJacob Faibussowitsch         PetscCall(MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix));
70329566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&benign_global));
703327b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
70341dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
70351dd7afcfSStefano Zampini       }
70361dd7afcfSStefano Zampini     }
703716909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
703816909a7fSStefano Zampini       IS             is_global;
703916909a7fSStefano Zampini       const PetscInt *gidxs;
704016909a7fSStefano Zampini 
70419566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&gidxs));
70429566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global));
70439566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&gidxs));
70449566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change));
70459566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is_global));
704616909a7fSStefano Zampini     }
70471dd7afcfSStefano Zampini   }
70481dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
70499566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->work_change));
7050b9b85e73SStefano Zampini   }
7051a717540cSStefano Zampini 
705272b8c272SStefano Zampini   if (!pcbddc->fake_change) {
70534f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
70544f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
70554f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
70564f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
7057019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
7058019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
7059019a44ceSStefano Zampini       pcbddc->local_primal_size++;
7060019a44ceSStefano Zampini     }
7061019a44ceSStefano Zampini 
7062019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
7063727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
7064727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
70659566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc,&pcbddc->new_primal_space_local));
7066c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
70670e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
70689566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc,&pcbddc->new_primal_space_local));
7069727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
7070727cdba6SStefano Zampini       }
70710e6343abSStefano Zampini     }
7072727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
70731c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
707472b8c272SStefano Zampini   }
70759566063dSJacob Faibussowitsch   PetscCall(PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult));
7076727cdba6SStefano Zampini 
7077a717540cSStefano Zampini   /* flush dbg viewer */
70781baa6e33SBarry Smith   if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
7079a717540cSStefano Zampini 
7080e310c8b4SStefano Zampini   /* free workspace */
70819566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&qr_needed_idx));
70829566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&change_basis));
708308122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
70849566063dSJacob Faibussowitsch     PetscCall(PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n));
70859566063dSJacob Faibussowitsch     PetscCall(PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B));
708608122e43SStefano Zampini   } else {
7087d0609cedSBarry Smith     PetscCall(PetscFree5(pcbddc->adaptive_constraints_n,pcbddc->adaptive_constraints_idxs_ptr,pcbddc->adaptive_constraints_data_ptr,pcbddc->adaptive_constraints_idxs,pcbddc->adaptive_constraints_data));
70889566063dSJacob Faibussowitsch     PetscCall(PetscFree(constraints_n));
70899566063dSJacob Faibussowitsch     PetscCall(PetscFree(constraints_idxs_B));
709008122e43SStefano Zampini   }
7091674ae819SStefano Zampini   PetscFunctionReturn(0);
7092674ae819SStefano Zampini }
7093674ae819SStefano Zampini 
7094674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
7095674ae819SStefano Zampini {
709671582508SStefano Zampini   ISLocalToGlobalMapping map;
7097674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7098674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
709966da6bd7Sstefano_zampini   PetscInt               i,N;
710066da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
7101674ae819SStefano Zampini 
7102674ae819SStefano Zampini   PetscFunctionBegin;
71038af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
7104b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
71058e61c736SStefano Zampini     /* Reset previously computed graph */
71069566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphReset(pcbddc->mat_graph));
7107674ae819SStefano Zampini     /* Init local Graph struct */
71089566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->pmat,&N,NULL));
71099566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(pc->pmat,&map,NULL));
71109566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount));
7111674ae819SStefano Zampini 
71127a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
71139566063dSJacob Faibussowitsch       PetscCall(PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local));
71147a0e7b2cSstefano_zampini     }
7115575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
71162472a847SBarry Smith     PetscCheck(!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 %" PetscInt_FMT ", expected %" PetscInt_FMT,pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
71179577ea80SStefano Zampini 
7118674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
711966da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
71204d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
71214d379d7bSStefano Zampini       PetscInt  nvtxs;
7122e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
7123674ae819SStefano Zampini 
71249566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row));
71252fffb893SStefano Zampini       if (flg_row) {
71269566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES));
7127b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
71282fffb893SStefano Zampini       }
71299566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row));
713066da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
7131674ae819SStefano Zampini     }
71321baa6e33SBarry Smith     if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
7133674ae819SStefano Zampini 
7134ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
7135ab8c8b98SStefano Zampini       PetscReal    *lcoords;
7136ab8c8b98SStefano Zampini       PetscInt     n;
7137ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
7138ab8c8b98SStefano Zampini 
71394f819b78SStefano Zampini       /* TODO: support for blocked */
714063a3b9bcSJacob Faibussowitsch       PetscCheck(pcbddc->mat_graph->cnloc == pc->pmat->rmap->n,PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local coordinates! Got %" PetscInt_FMT ", expected %" PetscInt_FMT,pcbddc->mat_graph->cnloc,pc->pmat->rmap->n);
71419566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(matis->A,&n,NULL));
71429566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords));
71439566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype));
71449566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_commit(&dimrealtype));
71459566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords,MPI_REPLACE));
71469566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords,MPI_REPLACE));
71479566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_free(&dimrealtype));
71489566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddc->mat_graph->coords));
7149ab8c8b98SStefano Zampini 
7150ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
7151ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
7152ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
7153ab8c8b98SStefano Zampini     }
71542472a847SBarry Smith     PetscCheck(!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 %" PetscInt_FMT ", expected %" PetscInt_FMT,pcbddc->mat_graph->cnloc,pcbddc->mat_graph->nvtxs);
7155625961bdSStefano Zampini     pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected);
7156ab8c8b98SStefano Zampini 
7157674ae819SStefano Zampini     /* Setup of Graph */
71584b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
71599566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphSetUp(pcbddc->mat_graph,pcbddc->vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local));
7160674ae819SStefano Zampini 
71614f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
71624f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
716320c3699dSStefano Zampini       PetscInt *local_subs,n,totn;
71644f1b2e48SStefano Zampini 
71659566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(matis->A,&n,NULL));
71669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n,&local_subs));
716720c3699dSStefano Zampini       for (i=0;i<n;i++) local_subs[i] = pcbddc->n_local_subs;
71684f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
71694f1b2e48SStefano Zampini         const PetscInt *idxs;
71704f1b2e48SStefano Zampini         PetscInt       nl,j;
71714f1b2e48SStefano Zampini 
71729566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(pcbddc->local_subs[i],&nl));
71739566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(pcbddc->local_subs[i],&idxs));
717471582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
71759566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(pcbddc->local_subs[i],&idxs));
71764f1b2e48SStefano Zampini       }
717720c3699dSStefano Zampini       for (i=0,totn=0;i<n;i++) totn = PetscMax(totn,local_subs[i]);
717820c3699dSStefano Zampini       pcbddc->mat_graph->n_local_subs = totn + 1;
71794f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
71804f1b2e48SStefano Zampini     }
71818af8fcf9SStefano Zampini   }
71824f1b2e48SStefano Zampini 
7183cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
7184674ae819SStefano Zampini     /* Graph's connected components analysis */
71859566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph));
718671582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
71874f819b78SStefano Zampini     pcbddc->corner_selected = pcbddc->corner_selection;
71888af8fcf9SStefano Zampini   }
718966da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
7190674ae819SStefano Zampini   PetscFunctionReturn(0);
7191674ae819SStefano Zampini }
7192674ae819SStefano Zampini 
7193295df10fSStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[])
71949a7d3425SStefano Zampini {
7195295df10fSStefano Zampini   PetscInt       i,j,n;
71969a7d3425SStefano Zampini   PetscScalar    *alphas;
7197295df10fSStefano Zampini   PetscReal      norm,*onorms;
71989a7d3425SStefano Zampini 
71999a7d3425SStefano Zampini   PetscFunctionBegin;
7200295df10fSStefano Zampini   n = *nio;
72018c0031efSStefano Zampini   if (!n) PetscFunctionReturn(0);
72029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(n,&alphas,n,&onorms));
72039566063dSJacob Faibussowitsch   PetscCall(VecNormalize(vecs[0],&norm));
720492cccca0SStefano Zampini   if (norm < PETSC_SMALL) {
7205295df10fSStefano Zampini     onorms[0] = 0.0;
72069566063dSJacob Faibussowitsch     PetscCall(VecSet(vecs[0],0.0));
7207295df10fSStefano Zampini   } else {
7208295df10fSStefano Zampini     onorms[0] = norm;
720992cccca0SStefano Zampini   }
7210295df10fSStefano Zampini 
72118c0031efSStefano Zampini   for (i=1;i<n;i++) {
72129566063dSJacob Faibussowitsch     PetscCall(VecMDot(vecs[i],i,vecs,alphas));
72138c0031efSStefano Zampini     for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]);
72149566063dSJacob Faibussowitsch     PetscCall(VecMAXPY(vecs[i],i,alphas,vecs));
72159566063dSJacob Faibussowitsch     PetscCall(VecNormalize(vecs[i],&norm));
721692cccca0SStefano Zampini     if (norm < PETSC_SMALL) {
7217295df10fSStefano Zampini       onorms[i] = 0.0;
72189566063dSJacob Faibussowitsch       PetscCall(VecSet(vecs[i],0.0));
7219295df10fSStefano Zampini     } else {
7220295df10fSStefano Zampini       onorms[i] = norm;
722192cccca0SStefano Zampini     }
72229a7d3425SStefano Zampini   }
7223295df10fSStefano Zampini   /* push nonzero vectors at the beginning */
7224295df10fSStefano Zampini   for (i=0;i<n;i++) {
7225295df10fSStefano Zampini     if (onorms[i] == 0.0) {
7226295df10fSStefano Zampini       for (j=i+1;j<n;j++) {
7227295df10fSStefano Zampini         if (onorms[j] != 0.0) {
72289566063dSJacob Faibussowitsch           PetscCall(VecCopy(vecs[j],vecs[i]));
7229295df10fSStefano Zampini           onorms[j] = 0.0;
7230295df10fSStefano Zampini         }
7231295df10fSStefano Zampini       }
7232295df10fSStefano Zampini     }
7233295df10fSStefano Zampini   }
7234295df10fSStefano Zampini   for (i=0,*nio=0;i<n;i++) *nio += onorms[i] != 0.0 ? 1 : 0;
72359566063dSJacob Faibussowitsch   PetscCall(PetscFree2(alphas,onorms));
72369a7d3425SStefano Zampini   PetscFunctionReturn(0);
72379a7d3425SStefano Zampini }
72389a7d3425SStefano Zampini 
7239bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
7240e7931f94SStefano Zampini {
7241e432b41dSStefano Zampini   ISLocalToGlobalMapping mapping;
724257de7509SStefano Zampini   Mat                    A;
7243e7931f94SStefano Zampini   PetscInt               n_neighs,*neighs,*n_shared,**shared;
7244e7931f94SStefano Zampini   PetscMPIInt            size,rank,color;
724552e5ac9dSStefano Zampini   PetscInt               *xadj,*adjncy;
724652e5ac9dSStefano Zampini   PetscInt               *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
7247bb360cb4SStefano Zampini   PetscInt               im_active,active_procs,N,n,i,j,threshold = 2;
724857de7509SStefano Zampini   PetscInt               void_procs,*procs_candidates = NULL;
724927b6a85dSStefano Zampini   PetscInt               xadj_count,*count;
725027b6a85dSStefano Zampini   PetscBool              ismatis,use_vwgt=PETSC_FALSE;
725127b6a85dSStefano Zampini   PetscSubcomm           psubcomm;
725227b6a85dSStefano Zampini   MPI_Comm               subcomm;
7253a57a6d2fSStefano Zampini 
7254e7931f94SStefano Zampini   PetscFunctionBegin;
725557de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
72569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis));
725728b400f6SJacob 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);
725857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
725957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
726063a3b9bcSJacob Faibussowitsch   PetscCheck(*n_subdomains >0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %" PetscInt_FMT,*n_subdomains);
726157de7509SStefano Zampini 
726257de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
72639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
72649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank));
72659566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(mat,&A));
72669566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&n,NULL));
7267bb360cb4SStefano Zampini   im_active = !!n;
72681c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
726957de7509SStefano Zampini   void_procs = size - active_procs;
727057de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
727157de7509SStefano Zampini   if (void_procs) {
727257de7509SStefano Zampini     PetscInt ncand;
727357de7509SStefano Zampini 
727457de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
72759566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size,&procs_candidates));
72769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat)));
727757de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
727857de7509SStefano Zampini       if (!procs_candidates[i]) {
727957de7509SStefano Zampini         procs_candidates[ncand++] = i;
728057de7509SStefano Zampini       }
728157de7509SStefano Zampini     }
728257de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
728357de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
728457de7509SStefano Zampini   }
728557de7509SStefano Zampini 
7286bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
72879dddd249SSatish Balay      number of subdomains requested 1 -> send to rank-0 or first candidate in voids  */
72889566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&N,NULL));
7289bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
729014f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
729114f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
729214f0bfb9SStefano Zampini     else dest = rank;
729357de7509SStefano Zampini     if (im_active) {
729457de7509SStefano Zampini       issize = 1;
729557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
729614f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
729757de7509SStefano Zampini       } else {
729814f0bfb9SStefano Zampini         isidx = dest;
729957de7509SStefano Zampini       }
730057de7509SStefano Zampini     } else {
730157de7509SStefano Zampini       issize = 0;
730257de7509SStefano Zampini       isidx = -1;
730357de7509SStefano Zampini     }
7304bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
73059566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends));
73069566063dSJacob Faibussowitsch     PetscCall(PetscFree(procs_candidates));
730757de7509SStefano Zampini     PetscFunctionReturn(0);
730857de7509SStefano Zampini   }
73099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL));
73109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL));
731127b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
7312e7931f94SStefano Zampini 
7313e7931f94SStefano Zampini   /* Get info on mapping */
73149566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalToGlobalMapping(mat,&mapping,NULL));
73159566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetInfo(mapping,&n_neighs,&neighs,&n_shared,&shared));
7316e7931f94SStefano Zampini 
7317e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
73189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2,&xadj));
7319e7931f94SStefano Zampini   xadj[0] = 0;
7320e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
73219566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(xadj[1],&adjncy));
73229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(xadj[1],&adjncy_wgt));
73239566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(n,&count));
732427b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
732527b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
732627b6a85dSStefano Zampini       count[shared[i][j]] += 1;
7327e7931f94SStefano Zampini 
732827b6a85dSStefano Zampini   xadj_count = 0;
73292b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
733027b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
733127b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
7332d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
7333d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
7334d023bfaeSStefano Zampini         xadj_count++;
733527b6a85dSStefano Zampini         break;
733627b6a85dSStefano Zampini       }
7337e7931f94SStefano Zampini     }
7338e7931f94SStefano Zampini   }
7339d023bfaeSStefano Zampini   xadj[1] = xadj_count;
73409566063dSJacob Faibussowitsch   PetscCall(PetscFree(count));
73419566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreInfo(mapping,&n_neighs,&neighs,&n_shared,&shared));
73429566063dSJacob Faibussowitsch   PetscCall(PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt));
7343e7931f94SStefano Zampini 
73449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1,&ranks_send_to_idx));
7345e7931f94SStefano Zampini 
734627b6a85dSStefano Zampini   /* Restrict work on active processes only */
73479566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(im_active,&color));
734827b6a85dSStefano Zampini   if (void_procs) {
73499566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm));
73509566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetNumber(psubcomm,2)); /* 2 groups, active process and not active processes */
73519566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetTypeGeneral(psubcomm,color,rank));
735227b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
735327b6a85dSStefano Zampini   } else {
735427b6a85dSStefano Zampini     psubcomm = NULL;
735527b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
735627b6a85dSStefano Zampini   }
735727b6a85dSStefano Zampini 
735827b6a85dSStefano Zampini   v_wgt = NULL;
735927b6a85dSStefano Zampini   if (!color) {
73609566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
73619566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
73629566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy_wgt));
7363c8587f34SStefano Zampini   } else {
736452e5ac9dSStefano Zampini     Mat             subdomain_adj;
736552e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
736652e5ac9dSStefano Zampini     MatPartitioning partitioner;
736727b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
736852e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
736957de7509SStefano Zampini     PetscMPIInt     size;
7370b0c7d250SStefano Zampini     PetscBool       aggregate;
7371b0c7d250SStefano Zampini 
73729566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(subcomm,&size));
737327b6a85dSStefano Zampini     if (void_procs) {
737427b6a85dSStefano Zampini       PetscInt prank = rank;
73759566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size,&oldranks));
73769566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm));
7377e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
73789566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]));
7379c8587f34SStefano Zampini       }
73809566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt));
738127b6a85dSStefano Zampini     } else {
738227b6a85dSStefano Zampini       oldranks = NULL;
738327b6a85dSStefano Zampini     }
7384b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
738527b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
7386b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
7387b0c7d250SStefano Zampini       PetscMPIInt nrank;
7388b0c7d250SStefano Zampini       PetscScalar *vals;
7389b0c7d250SStefano Zampini 
73909566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(subcomm,&nrank));
7391b0c7d250SStefano Zampini       lrows = 0;
7392b0c7d250SStefano Zampini       if (nrank<redprocs) {
7393b0c7d250SStefano Zampini         lrows = size/redprocs;
7394b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7395b0c7d250SStefano Zampini       }
73969566063dSJacob Faibussowitsch       PetscCall(MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj));
73979566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(subdomain_adj,&rstart,&rend));
73989566063dSJacob Faibussowitsch       PetscCall(MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE));
73999566063dSJacob Faibussowitsch       PetscCall(MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE));
7400b0c7d250SStefano Zampini       row = nrank;
7401b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7402b0c7d250SStefano Zampini       cols = adjncy;
74039566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(ncols,&vals));
7404b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
74059566063dSJacob Faibussowitsch       PetscCall(MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES));
74069566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY));
74079566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY));
74089566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
74099566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
74109566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy_wgt));
74119566063dSJacob Faibussowitsch       PetscCall(PetscFree(vals));
741227b6a85dSStefano Zampini       if (use_vwgt) {
741327b6a85dSStefano Zampini         Vec               v;
741427b6a85dSStefano Zampini         const PetscScalar *array;
741527b6a85dSStefano Zampini         PetscInt          nl;
741627b6a85dSStefano Zampini 
74179566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(subdomain_adj,&v,NULL));
74189566063dSJacob Faibussowitsch         PetscCall(VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES));
74199566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(v));
74209566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(v));
74219566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(v,&nl));
74229566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(v,&array));
74239566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nl,&v_wgt));
742422db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
74259566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(v,&array));
74269566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&v));
742727b6a85dSStefano Zampini       }
7428b0c7d250SStefano Zampini     } else {
74299566063dSJacob Faibussowitsch       PetscCall(MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj));
743027b6a85dSStefano Zampini       if (use_vwgt) {
74319566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(1,&v_wgt));
7432bb360cb4SStefano Zampini         v_wgt[0] = n;
743327b6a85dSStefano Zampini       }
7434b0c7d250SStefano Zampini     }
74359566063dSJacob Faibussowitsch     /* PetscCall(MatView(subdomain_adj,0)); */
7436e7931f94SStefano Zampini 
7437e7931f94SStefano Zampini     /* Partition */
74389566063dSJacob Faibussowitsch     PetscCall(MatPartitioningCreate(subcomm,&partitioner));
7439ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH)
74409566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetType(partitioner,MATPARTITIONINGPTSCOTCH));
7441ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS)
74429566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetType(partitioner,MATPARTITIONINGPARMETIS));
7443ce64c636SStefano Zampini #else
74449566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetType(partitioner,MATPARTITIONINGAVERAGE));
7445ce64c636SStefano Zampini #endif
74469566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetAdjacency(partitioner,subdomain_adj));
74471baa6e33SBarry Smith     if (v_wgt) PetscCall(MatPartitioningSetVertexWeights(partitioner,v_wgt));
744857de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
74499566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetNParts(partitioner,*n_subdomains));
74509566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetFromOptions(partitioner));
74519566063dSJacob Faibussowitsch     PetscCall(MatPartitioningApply(partitioner,&new_ranks));
74529566063dSJacob Faibussowitsch     /* PetscCall(MatPartitioningView(partitioner,0)); */
7453e7931f94SStefano Zampini 
745452e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
74559566063dSJacob Faibussowitsch     PetscCall(ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig));
74569566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&new_ranks));
74579566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices));
745857de7509SStefano Zampini     if (!aggregate) {
745957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
74606bdcaf15SBarry Smith         PetscAssert(oldranks,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
746157de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
746227b6a85dSStefano Zampini       } else if (oldranks) {
7463b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
746427b6a85dSStefano Zampini       } else {
746527b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
746657de7509SStefano Zampini       }
746728143c3dSStefano Zampini     } else {
74687fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7469b0c7d250SStefano Zampini       PetscMPIInt tag;
7470b0c7d250SStefano Zampini       MPI_Request *reqs;
7471b0c7d250SStefano Zampini 
74729566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag));
74739566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(rend-rstart,&reqs));
7474b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
74759566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]));
747628143c3dSStefano Zampini       }
74779566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE));
74789566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE));
74799566063dSJacob Faibussowitsch       PetscCall(PetscFree(reqs));
748057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
74816bdcaf15SBarry Smith         PetscAssert(oldranks,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
74827fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
748327b6a85dSStefano Zampini       } else if (oldranks) {
74847fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
748527b6a85dSStefano Zampini       } else {
74867fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7487e7931f94SStefano Zampini       }
748857de7509SStefano Zampini     }
74899566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices));
7490e7931f94SStefano Zampini     /* clean up */
74919566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldranks));
74929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&new_ranks_contig));
74939566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&subdomain_adj));
74949566063dSJacob Faibussowitsch     PetscCall(MatPartitioningDestroy(&partitioner));
7495e7931f94SStefano Zampini   }
74969566063dSJacob Faibussowitsch   PetscCall(PetscSubcommDestroy(&psubcomm));
74979566063dSJacob Faibussowitsch   PetscCall(PetscFree(procs_candidates));
7498e7931f94SStefano Zampini 
7499e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7500e7931f94SStefano Zampini   i = 1;
750127b6a85dSStefano Zampini   if (!color) i=0;
75029566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends));
7503e7931f94SStefano Zampini   PetscFunctionReturn(0);
7504e7931f94SStefano Zampini }
7505e7931f94SStefano Zampini 
7506e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7507e7931f94SStefano Zampini 
75081e0482f5SStefano 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[])
7509e7931f94SStefano Zampini {
751070cf5478SStefano Zampini   Mat                    local_mat;
7511e7931f94SStefano Zampini   IS                     is_sends_internal;
75129d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
75131ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
75149d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7515e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7516e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7517e7931f94SStefano Zampini   const PetscInt*        is_indices;
7518e7931f94SStefano Zampini   MatType                new_local_type;
7519e7931f94SStefano Zampini   /* buffers */
7520e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
752128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
75229d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
75231683a169SBarry Smith   PetscScalar            *ptr_vals,*recv_buffer_vals;
75241683a169SBarry Smith   const PetscScalar      *send_buffer_vals;
75251ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7526e7931f94SStefano Zampini   /* MPI */
752728143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
752828143c3dSStefano Zampini   PetscSubcomm           subcomm;
7529e569e4e1SStefano Zampini   PetscMPIInt            n_sends,n_recvs,size;
753028143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
753128143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
75321ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
75331ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
75341ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7535e7931f94SStefano Zampini 
7536e7931f94SStefano Zampini   PetscFunctionBegin;
753757de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
75389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis));
75395f80ce2aSJacob 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);
754057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
754157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
754257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
754357de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
754457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
75451ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
75461ae86dd6SStefano Zampini   if (nvecs) {
754708401ef6SPierre Jolivet     PetscCheck(nvecs <= 1,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
75481ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
75491ae86dd6SStefano Zampini   }
755057de7509SStefano Zampini   /* further checks */
75519566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(mat,&local_mat));
75529566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense));
75535f80ce2aSJacob Faibussowitsch   PetscCheck(isdense,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
75549566063dSJacob Faibussowitsch   PetscCall(MatGetSize(local_mat,&rows,&cols));
75555f80ce2aSJacob Faibussowitsch   PetscCheck(rows == cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
755657de7509SStefano Zampini   if (reuse && *mat_n) {
755770cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
755857de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
75599566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis));
75605f80ce2aSJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
75619566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat,&mrows,&mcols));
75629566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*mat_n,&mnrows,&mncols));
756363a3b9bcSJacob Faibussowitsch     PetscCheck(mrows == mnrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %" PetscInt_FMT " != %" PetscInt_FMT,mrows,mnrows);
756463a3b9bcSJacob Faibussowitsch     PetscCheck(mcols == mncols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %" PetscInt_FMT " != %" PetscInt_FMT,mcols,mncols);
756570cf5478SStefano Zampini   }
75669566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(local_mat,&bs));
7567064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(mat,bs,1);
756857de7509SStefano Zampini 
7569e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7570e7931f94SStefano Zampini   if (!is_sends) {
75715f80ce2aSJacob Faibussowitsch     PetscCheck(n_subdomains,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
75729566063dSJacob Faibussowitsch     PetscCall(PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL));
7573c8587f34SStefano Zampini   } else {
75749566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)is_sends));
7575e7931f94SStefano Zampini     is_sends_internal = is_sends;
7576c8587f34SStefano Zampini   }
7577e7931f94SStefano Zampini 
7578e7931f94SStefano Zampini   /* get comm */
75799566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
7580e7931f94SStefano Zampini 
7581e7931f94SStefano Zampini   /* compute number of sends */
75829566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_sends_internal,&i));
75839566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(i,&n_sends));
7584e7931f94SStefano Zampini 
7585e7931f94SStefano Zampini   /* compute number of receives */
75869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
75879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&iflags));
75889566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(iflags,size));
75899566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_sends_internal,&is_indices));
7590e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
75919566063dSJacob Faibussowitsch   PetscCall(PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs));
75929566063dSJacob Faibussowitsch   PetscCall(PetscFree(iflags));
7593e7931f94SStefano Zampini 
759428143c3dSStefano Zampini   /* restrict comm if requested */
75950a545947SLisandro Dalcin   subcomm = NULL;
759628143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
759728143c3dSStefano Zampini   if (restrict_comm) {
7598779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7599779c1cceSStefano Zampini 
760028143c3dSStefano Zampini     color = 0;
760153a05cb3SStefano Zampini     if (restrict_full) {
76026aad120cSJose E. Roman       if (!n_recvs) color = 1; /* processes not receiving anything will not participate in new comm (full restriction) */
760353a05cb3SStefano Zampini     } else {
76046aad120cSJose E. Roman       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not participate in new comm */
760553a05cb3SStefano Zampini     }
76061c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm));
7607e569e4e1SStefano Zampini     subcommsize = size - subcommsize;
760828143c3dSStefano Zampini     /* check if reuse has been requested */
760957de7509SStefano Zampini     if (reuse) {
761028143c3dSStefano Zampini       if (*mat_n) {
761128143c3dSStefano Zampini         PetscMPIInt subcommsize2;
76129566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2));
76135f80ce2aSJacob Faibussowitsch         PetscCheck(subcommsize == subcommsize2,PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
761428143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
761528143c3dSStefano Zampini       } else {
761628143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
761728143c3dSStefano Zampini       }
761828143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7619779c1cceSStefano Zampini       PetscMPIInt rank;
7620779c1cceSStefano Zampini 
76219566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm,&rank));
76229566063dSJacob Faibussowitsch       PetscCall(PetscSubcommCreate(comm,&subcomm));
76239566063dSJacob Faibussowitsch       PetscCall(PetscSubcommSetNumber(subcomm,2));
76249566063dSJacob Faibussowitsch       PetscCall(PetscSubcommSetTypeGeneral(subcomm,color,rank));
7625306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
762628143c3dSStefano Zampini     }
762728143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
762828143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
762928143c3dSStefano Zampini   } else {
763028143c3dSStefano Zampini     comm_n = comm;
763128143c3dSStefano Zampini   }
763228143c3dSStefano Zampini 
7633e7931f94SStefano Zampini   /* prepare send/receive buffers */
76349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&ilengths_idxs));
76359566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(ilengths_idxs,size));
76369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&ilengths_vals));
76379566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(ilengths_vals,size));
763828143c3dSStefano Zampini   if (nis) {
76399566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(size,&ilengths_idxs_is));
764028143c3dSStefano Zampini   }
7641e7931f94SStefano Zampini 
764228143c3dSStefano Zampini   /* Get data from local matrices */
7643e432b41dSStefano Zampini   PetscCheck(isdense,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7644e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7645e7931f94SStefano Zampini     /*
7646e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7647e7931f94SStefano Zampini        send_buffer_idxs should contain:
7648e7931f94SStefano Zampini        - MatType_PRIVATE type
7649e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7650e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7651e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7652e7931f94SStefano Zampini     */
7653e432b41dSStefano Zampini   {
7654e432b41dSStefano Zampini     ISLocalToGlobalMapping mapping;
7655e432b41dSStefano Zampini 
76569566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(mat,&mapping,NULL));
76579566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(local_mat,&send_buffer_vals));
76589566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(mapping,&i));
76599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(i+2,&send_buffer_idxs));
7660e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7661e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
76629566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(mapping,(const PetscInt**)&ptr_idxs));
76639566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&send_buffer_idxs[2],ptr_idxs,i));
76649566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping,(const PetscInt**)&ptr_idxs));
76659566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(i,&len));
7666e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7667e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7668e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7669c8587f34SStefano Zampini     }
7670c8587f34SStefano Zampini   }
76719566063dSJacob Faibussowitsch   PetscCall(PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals));
767228143c3dSStefano Zampini   /* additional is (if any) */
767328143c3dSStefano Zampini   if (nis) {
767428143c3dSStefano Zampini     PetscMPIInt psum;
767528143c3dSStefano Zampini     PetscInt j;
767628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
767728143c3dSStefano Zampini       PetscInt plen;
76789566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(isarray[j],&plen));
76799566063dSJacob Faibussowitsch       PetscCall(PetscMPIIntCast(plen,&len));
76806aad120cSJose E. Roman       psum += len+1; /* indices + length */
768128143c3dSStefano Zampini     }
76829566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(psum,&send_buffer_idxs_is));
768328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
768428143c3dSStefano Zampini       PetscInt plen;
768528143c3dSStefano Zampini       const PetscInt *is_array_idxs;
76869566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(isarray[j],&plen));
768728143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
76889566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(isarray[j],&is_array_idxs));
76899566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen));
76909566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(isarray[j],&is_array_idxs));
76916aad120cSJose E. Roman       psum += plen+1; /* indices + length */
769228143c3dSStefano Zampini     }
769328143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
769428143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
769528143c3dSStefano Zampini     }
76969566063dSJacob Faibussowitsch     PetscCall(PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is));
769728143c3dSStefano Zampini   }
76989566063dSJacob Faibussowitsch   PetscCall(MatISRestoreLocalMat(mat,&local_mat));
769928143c3dSStefano Zampini 
7700e7931f94SStefano Zampini   buf_size_idxs = 0;
7701e7931f94SStefano Zampini   buf_size_vals = 0;
770228143c3dSStefano Zampini   buf_size_idxs_is = 0;
77031ae86dd6SStefano Zampini   buf_size_vecs = 0;
7704e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7705e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7706e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
770728143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
77081ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7709e7931f94SStefano Zampini   }
77109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_idxs,&recv_buffer_idxs));
77119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_vals,&recv_buffer_vals));
77129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is));
77139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_vecs,&recv_buffer_vecs));
7714e7931f94SStefano Zampini 
7715e7931f94SStefano Zampini   /* get new tags for clean communications */
77169566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag_idxs));
77179566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag_vals));
77189566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is));
77199566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag_vecs));
7720e7931f94SStefano Zampini 
7721e7931f94SStefano Zampini   /* allocate for requests */
77229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_sends,&send_req_idxs));
77239566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_sends,&send_req_vals));
77249566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_sends,&send_req_idxs_is));
77259566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_sends,&send_req_vecs));
77269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_recvs,&recv_req_idxs));
77279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_recvs,&recv_req_vals));
77289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_recvs,&recv_req_idxs_is));
77299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_recvs,&recv_req_vecs));
7730e7931f94SStefano Zampini 
7731e7931f94SStefano Zampini   /* communications */
7732e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7733e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
773428143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
77351ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7736e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7737e7931f94SStefano Zampini     source_dest = onodes[i];
77389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]));
77399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]));
7740e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7741e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
774228143c3dSStefano Zampini     if (nis) {
774357de7509SStefano Zampini       source_dest = onodes_is[i];
77449566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Irecv(ptr_idxs_is,olengths_idxs_is[i],MPIU_INT,source_dest,tag_idxs_is,comm,&recv_req_idxs_is[i]));
774528143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
774628143c3dSStefano Zampini     }
77471ae86dd6SStefano Zampini     if (nvecs) {
77481ae86dd6SStefano Zampini       source_dest = onodes[i];
77499566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]));
77501ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
77511ae86dd6SStefano Zampini     }
7752e7931f94SStefano Zampini   }
7753e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
77549566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(is_indices[i],&source_dest));
77559566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]));
77569566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Isend((PetscScalar*)send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]));
775728143c3dSStefano Zampini     if (nis) {
77589566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend(send_buffer_idxs_is,ilengths_idxs_is[source_dest],MPIU_INT,source_dest,tag_idxs_is,comm,&send_req_idxs_is[i]));
775928143c3dSStefano Zampini     }
77601ae86dd6SStefano Zampini     if (nvecs) {
77619566063dSJacob Faibussowitsch       PetscCall(VecGetArray(nnsp_vec[0],&send_buffer_vecs));
77629566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend(send_buffer_vecs,ilengths_idxs[source_dest]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&send_req_vecs[i]));
77631ae86dd6SStefano Zampini     }
7764e7931f94SStefano Zampini   }
77659566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_sends_internal,&is_indices));
77669566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_sends_internal));
7767e7931f94SStefano Zampini 
7768e7931f94SStefano Zampini   /* assemble new l2g map */
77699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE));
7770e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
77719d30be91SStefano Zampini   new_local_rows = 0;
7772e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
77739d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7774e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7775e7931f94SStefano Zampini   }
77769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(new_local_rows,&l2gmap_indices));
7777e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
77789d30be91SStefano Zampini   new_local_rows = 0;
7779e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
77809566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,*(ptr_idxs+1)));
77819d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7782e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7783e7931f94SStefano Zampini   }
77849566063dSJacob Faibussowitsch   PetscCall(PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices));
77859566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap));
77869566063dSJacob Faibussowitsch   PetscCall(PetscFree(l2gmap_indices));
7787e7931f94SStefano Zampini 
7788e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7789e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7790e7931f94SStefano 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) */
7791e7931f94SStefano Zampini   if (n_recvs) {
779228143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7793e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7794e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7795e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7796e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7797e7931f94SStefano Zampini         break;
7798e7931f94SStefano Zampini       }
7799e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7800e7931f94SStefano Zampini     }
7801e7931f94SStefano Zampini     switch (new_local_type_private) {
780228143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7803e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7804e7931f94SStefano Zampini         bs = 1;
7805e7931f94SStefano Zampini         break;
7806e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7807e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7808e7931f94SStefano Zampini         bs = 1;
7809e7931f94SStefano Zampini         break;
7810e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7811e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7812e7931f94SStefano Zampini         break;
7813e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7814e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7815e7931f94SStefano Zampini         break;
7816e7931f94SStefano Zampini       default:
781798921bdaSJacob Faibussowitsch         SETERRQ(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7818e7931f94SStefano Zampini     }
7819ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7820ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
782128143c3dSStefano Zampini     bs = 1;
7822e7931f94SStefano Zampini   }
7823e7931f94SStefano Zampini 
782470cf5478SStefano Zampini   /* create MATIS object if needed */
782557de7509SStefano Zampini   if (!reuse) {
78269566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat,&rows,&cols));
78279566063dSJacob Faibussowitsch     PetscCall(MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,l2gmap,mat_n));
782870cf5478SStefano Zampini   } else {
782970cf5478SStefano Zampini     /* it also destroys the local matrices */
783057de7509SStefano Zampini     if (*mat_n) {
78319566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap));
783257de7509SStefano Zampini     } else { /* this is a fake object */
78339566063dSJacob Faibussowitsch       PetscCall(MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,l2gmap,mat_n));
783457de7509SStefano Zampini     }
783570cf5478SStefano Zampini   }
78369566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(*mat_n,&local_mat));
78379566063dSJacob Faibussowitsch   PetscCall(MatSetType(local_mat,new_local_type));
78389d30be91SStefano Zampini 
78399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE));
78409d30be91SStefano Zampini 
78419d30be91SStefano Zampini   /* Global to local map of received indices */
78429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local)); /* needed for values insertion */
78439566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local));
78449566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap));
78459d30be91SStefano Zampini 
78469d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
78479d30be91SStefano Zampini   buf_size_idxs = 0;
78489d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
78499d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
78509d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
78519d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
78529d30be91SStefano Zampini   }
78539566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_idxs));
78549d30be91SStefano Zampini 
78559d30be91SStefano Zampini   /* set preallocation */
78569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense));
78579d30be91SStefano Zampini   if (!newisdense) {
78580a545947SLisandro Dalcin     PetscInt *new_local_nnz=NULL;
78599d30be91SStefano Zampini 
78609d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
78619d30be91SStefano Zampini     if (n_recvs) {
78629566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(new_local_rows,&new_local_nnz));
78639d30be91SStefano Zampini     }
78649d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
78659d30be91SStefano Zampini       PetscInt j;
78669d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
78679d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
78689d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
78699d30be91SStefano Zampini         }
78709d30be91SStefano Zampini       } else {
78719d30be91SStefano Zampini         /* TODO */
78729d30be91SStefano Zampini       }
78739d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
78749d30be91SStefano Zampini     }
78759d30be91SStefano Zampini     if (new_local_nnz) {
78769d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
78779566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz));
78789d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
78799566063dSJacob Faibussowitsch       PetscCall(MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz));
78809d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
78819566063dSJacob Faibussowitsch       PetscCall(MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz));
78829d30be91SStefano Zampini     } else {
78839566063dSJacob Faibussowitsch       PetscCall(MatSetUp(local_mat));
78849d30be91SStefano Zampini     }
78859566063dSJacob Faibussowitsch     PetscCall(PetscFree(new_local_nnz));
78869d30be91SStefano Zampini   } else {
78879566063dSJacob Faibussowitsch     PetscCall(MatSetUp(local_mat));
78889d30be91SStefano Zampini   }
7889e7931f94SStefano Zampini 
7890e7931f94SStefano Zampini   /* set values */
7891e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
78929d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7893e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7894e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
78959566063dSJacob Faibussowitsch       PetscCall(MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE));
78969566063dSJacob Faibussowitsch       PetscCall(MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES));
78979566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY));
78989566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY));
78999566063dSJacob Faibussowitsch       PetscCall(MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE));
790028143c3dSStefano Zampini     } else {
790128143c3dSStefano Zampini       /* TODO */
7902e7931f94SStefano Zampini     }
7903e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7904e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7905e7931f94SStefano Zampini   }
79069566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY));
79079566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY));
79089566063dSJacob Faibussowitsch   PetscCall(MatISRestoreLocalMat(*mat_n,&local_mat));
79099566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY));
79109566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY));
79119566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_vals));
7912e7931f94SStefano Zampini 
7913dfd14d43SStefano Zampini #if 0
791428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7915e7931f94SStefano Zampini     Vec       lvec,rvec;
7916e7931f94SStefano Zampini     PetscReal infty_error;
7917e7931f94SStefano Zampini 
79189566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(mat,&rvec,&lvec));
79199566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(rvec,NULL));
79209566063dSJacob Faibussowitsch     PetscCall(MatMult(mat,rvec,lvec));
79219566063dSJacob Faibussowitsch     PetscCall(VecScale(lvec,-1.0));
79229566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(*mat_n,rvec,lvec,lvec));
79239566063dSJacob Faibussowitsch     PetscCall(VecNorm(lvec,NORM_INFINITY,&infty_error));
79249566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error));
79259566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rvec));
79269566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lvec));
7927e7931f94SStefano Zampini   }
792828143c3dSStefano Zampini #endif
7929e7931f94SStefano Zampini 
793028143c3dSStefano Zampini   /* assemble new additional is (if any) */
793128143c3dSStefano Zampini   if (nis) {
793228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
793328143c3dSStefano Zampini 
79349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE));
79359566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nis,&count_is));
793628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
793728143c3dSStefano Zampini     psum = 0;
793828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
793928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
794028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
794128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
794228143c3dSStefano Zampini         psum += plen;
794328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
794428143c3dSStefano Zampini       }
794528143c3dSStefano Zampini     }
79469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nis,&temp_idxs));
79479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(psum,&temp_idxs[0]));
794828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
794928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
795028143c3dSStefano Zampini     }
79519566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(count_is,nis));
795228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
795328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
795428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
795528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
79569566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen));
795728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
795828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
795928143c3dSStefano Zampini       }
796028143c3dSStefano Zampini     }
796128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
79629566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isarray[i]));
79639566063dSJacob Faibussowitsch       PetscCall(PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]));
79649566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]));
796528143c3dSStefano Zampini     }
79669566063dSJacob Faibussowitsch     PetscCall(PetscFree(count_is));
79679566063dSJacob Faibussowitsch     PetscCall(PetscFree(temp_idxs[0]));
79689566063dSJacob Faibussowitsch     PetscCall(PetscFree(temp_idxs));
796928143c3dSStefano Zampini   }
7970e7931f94SStefano Zampini   /* free workspace */
79719566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_idxs_is));
79729566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE));
79739566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_buffer_idxs));
79749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE));
7975e7931f94SStefano Zampini   if (isdense) {
79769566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(mat,&local_mat));
79779566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(local_mat,&send_buffer_vals));
79789566063dSJacob Faibussowitsch     PetscCall(MatISRestoreLocalMat(mat,&local_mat));
7979e7931f94SStefano Zampini   } else {
79809566063dSJacob Faibussowitsch     /* PetscCall(PetscFree(send_buffer_vals)); */
7981e7931f94SStefano Zampini   }
798228143c3dSStefano Zampini   if (nis) {
79839566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE));
79849566063dSJacob Faibussowitsch     PetscCall(PetscFree(send_buffer_idxs_is));
798528143c3dSStefano Zampini   }
79861ae86dd6SStefano Zampini 
79871ae86dd6SStefano Zampini   if (nvecs) {
79889566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE));
79899566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE));
79909566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(nnsp_vec[0],&send_buffer_vecs));
79919566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nnsp_vec[0]));
79929566063dSJacob Faibussowitsch     PetscCall(VecCreate(comm_n,&nnsp_vec[0]));
79939566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE));
79949566063dSJacob Faibussowitsch     PetscCall(VecSetType(nnsp_vec[0],VECSTANDARD));
79951ae86dd6SStefano Zampini     /* set values */
79961ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
79971ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
79989566063dSJacob Faibussowitsch     PetscCall(VecGetArray(nnsp_vec[0],&send_buffer_vecs));
79991ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
80001ae86dd6SStefano Zampini       PetscInt j;
80011ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
80021ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
80031ae86dd6SStefano Zampini       }
80041ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
80051ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
80061ae86dd6SStefano Zampini     }
80079566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(nnsp_vec[0],&send_buffer_vecs));
80089566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(nnsp_vec[0]));
80099566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(nnsp_vec[0]));
80101ae86dd6SStefano Zampini   }
80111ae86dd6SStefano Zampini 
80129566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_vecs));
80139566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_idxs_local));
80149566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_req_idxs));
80159566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_req_vals));
80169566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_req_vecs));
80179566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_req_idxs_is));
80189566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_req_idxs));
80199566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_req_vals));
80209566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_req_vecs));
80219566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_req_idxs_is));
80229566063dSJacob Faibussowitsch   PetscCall(PetscFree(ilengths_vals));
80239566063dSJacob Faibussowitsch   PetscCall(PetscFree(ilengths_idxs));
80249566063dSJacob Faibussowitsch   PetscCall(PetscFree(olengths_vals));
80259566063dSJacob Faibussowitsch   PetscCall(PetscFree(olengths_idxs));
80269566063dSJacob Faibussowitsch   PetscCall(PetscFree(onodes));
802728143c3dSStefano Zampini   if (nis) {
80289566063dSJacob Faibussowitsch     PetscCall(PetscFree(ilengths_idxs_is));
80299566063dSJacob Faibussowitsch     PetscCall(PetscFree(olengths_idxs_is));
80309566063dSJacob Faibussowitsch     PetscCall(PetscFree(onodes_is));
803128143c3dSStefano Zampini   }
80329566063dSJacob Faibussowitsch   PetscCall(PetscSubcommDestroy(&subcomm));
80336aad120cSJose E. Roman   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not participate */
80349566063dSJacob Faibussowitsch     PetscCall(MatDestroy(mat_n));
803528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
80369566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isarray[i]));
803728143c3dSStefano Zampini     }
80381ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
80399566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&nnsp_vec[0]));
80401ae86dd6SStefano Zampini     }
804153a05cb3SStefano Zampini     *mat_n = NULL;
804228143c3dSStefano Zampini   }
8043e7931f94SStefano Zampini   PetscFunctionReturn(0);
8044e7931f94SStefano Zampini }
8045a57a6d2fSStefano Zampini 
804612edc857SStefano Zampini /* temporary hack into ksp private data structure */
8047af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
804812edc857SStefano Zampini 
8049c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
8050c8587f34SStefano Zampini {
8051c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
8052c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
805320a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
80541ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
80551e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
80569881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
805720a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
80584f819b78SStefano Zampini   IS                     coarse_is,*isarray,corners;
80596e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
806030368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
8061e569e4e1SStefano Zampini   PetscInt               coarse_eqs_per_proc;
8062f9eb5b7dSStefano Zampini   PC                     pc_temp;
8063c8587f34SStefano Zampini   PCType                 coarse_pc_type;
8064c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
8065f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
80667274672aSStefano Zampini   PetscBool              coarse_reuse;
80671e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
806868457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
806922bc73bbSStefano Zampini   PetscScalar            *array;
807057de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
807157de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
8072e569e4e1SStefano Zampini   PetscMPIInt            size;
8073fdc09c96SStefano Zampini 
8074c8587f34SStefano Zampini   PetscFunctionBegin;
80759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0));
8076c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
807768457ee5SStefano 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 */
8078fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
80795a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
80807de4f681Sstefano_zampini 
80817de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
8082fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
80839566063dSJacob Faibussowitsch     PetscCall(PetscFree(pcbddc->global_primal_indices));
80849566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices));
8085f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
8086fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
808751bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
808851bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
80899566063dSJacob Faibussowitsch         PetscCall(KSPReset(pcbddc->coarse_ksp));
8090fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
8091fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
8092fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
8093f4ddd8eeSStefano Zampini       }
8094fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
8095fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
8096f4ddd8eeSStefano Zampini     }
809770cf5478SStefano Zampini     /* reset any subassembling information */
809857de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
80999566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pcbddc->coarse_subassembling));
810057de7509SStefano Zampini     }
81016e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
8102fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
8103f4ddd8eeSStefano Zampini   }
810457de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
81059566063dSJacob Faibussowitsch     PetscCall(KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL));
81069566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarse_mat));
810757de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
810818a45a71SStefano Zampini   } else {
810957de7509SStefano Zampini     coarse_mat = NULL;
811057de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
81116e683305SStefano Zampini   }
8112e7931f94SStefano Zampini 
8113abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
81149566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is));
81159566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg));
8116abbbba34SStefano Zampini 
8117abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
81189566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_submat_dense));
81199566063dSJacob Faibussowitsch   PetscCall(MatCreateIS(PetscObjectComm((PetscObject)pc),1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_islg,coarse_islg,&t_coarse_mat_is));
81209566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense));
81219566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY));
81229566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY));
81239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarse_submat_dense));
8124abbbba34SStefano Zampini 
812557de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
812657de7509SStefano Zampini   im_active = !!(pcis->n);
81271c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc)));
812857de7509SStefano Zampini 
812914f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
813028d58a37SPierre Jolivet   /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */
813157de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
81329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
813357de7509SStefano Zampini   coarse_mat_is        = NULL;
813457de7509SStefano Zampini   multilevel_allowed   = PETSC_FALSE;
813557de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
8136e569e4e1SStefano Zampini   coarse_eqs_per_proc  = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
8137ce64c636SStefano Zampini   if (coarse_eqs_per_proc < 0) coarse_eqs_per_proc = pcbddc->coarse_size;
813857de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
8139e569e4e1SStefano Zampini   if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE;
814057de7509SStefano Zampini   if (multilevel_requested) {
814157de7509SStefano Zampini     ncoarse    = active_procs/pcbddc->coarsening_ratio;
814257de7509SStefano Zampini     restr      = PETSC_FALSE;
814357de7509SStefano Zampini     full_restr = PETSC_FALSE;
814457de7509SStefano Zampini   } else {
8145e569e4e1SStefano Zampini     ncoarse    = pcbddc->coarse_size/coarse_eqs_per_proc + !!(pcbddc->coarse_size%coarse_eqs_per_proc);
814657de7509SStefano Zampini     restr      = PETSC_TRUE;
814757de7509SStefano Zampini     full_restr = PETSC_TRUE;
814857de7509SStefano Zampini   }
8149e569e4e1SStefano Zampini   if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
815057de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
815157de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
8152a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
8153bb360cb4SStefano Zampini       if (multilevel_requested) {
81549566063dSJacob Faibussowitsch         PetscCall(PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void));
8155bb360cb4SStefano Zampini       } else {
81569566063dSJacob Faibussowitsch         PetscCall(PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void));
8157bb360cb4SStefano Zampini       }
8158a198735bSStefano Zampini     } else {
81597de4f681Sstefano_zampini       PetscMPIInt rank;
816028d58a37SPierre Jolivet 
81619566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
8162e569e4e1SStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
81639566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling));
8164a198735bSStefano Zampini     }
816557de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
816657de7509SStefano Zampini     PetscInt    psum;
816757de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
816857de7509SStefano Zampini     else psum = 0;
81691c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc)));
8170075e25bcSStefano Zampini     have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE;
817157de7509SStefano Zampini   }
817257de7509SStefano Zampini   /* determine if we can go multilevel */
817357de7509SStefano Zampini   if (multilevel_requested) {
817457de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
817557de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
817657de7509SStefano Zampini   }
817757de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
817857de7509SStefano Zampini 
8179e4d548c7SStefano Zampini   /* dump subassembling pattern */
8180e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
81819566063dSJacob Faibussowitsch     PetscCall(ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer));
8182e4d548c7SStefano Zampini   }
81836e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
81841e0482f5SStefano Zampini   nedcfield = -1;
81854f819b78SStefano Zampini   corners = NULL;
81868966356dSPierre Jolivet   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */
81876e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
81886e683305SStefano Zampini     const PetscInt         *idxs;
81896e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
81906e683305SStefano Zampini 
81916e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
81929566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap));
81936e683305SStefano Zampini     /* allocate space for temporary storage */
81949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcbddc->local_primal_size,&tidxs));
81959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcbddc->local_primal_size,&tidxs2));
81966e683305SStefano Zampini     /* allocate for IS array */
81976e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
81981e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
81991e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
82001e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
82011e0482f5SStefano Zampini       } else {
82021e0482f5SStefano Zampini         nedcfield = 0;
820363a3b9bcSJacob Faibussowitsch         PetscCheck(!nisdofs,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%" PetscInt_FMT ")",nisdofs);
82041e0482f5SStefano Zampini         nisdofs = 1;
82051e0482f5SStefano Zampini       }
82061e0482f5SStefano Zampini     }
82076e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
820827b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
820930368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
82109566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nis,&isarray));
82116e683305SStefano Zampini     /* dofs splitting */
82126e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
82139566063dSJacob Faibussowitsch       /* PetscCall(ISView(pcbddc->ISForDofsLocal[i],0)); */
82141e0482f5SStefano Zampini       if (nedcfield != i) {
82159566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize));
82169566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs));
82179566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs));
82189566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs));
82191e0482f5SStefano Zampini       } else {
82209566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(pcbddc->nedclocal,&tsize));
82219566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(pcbddc->nedclocal,&idxs));
82229566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs));
822363a3b9bcSJacob Faibussowitsch         PetscCheck(tsize == nout,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %" PetscInt_FMT " != %" PetscInt_FMT,tsize,nout);
82249566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(pcbddc->nedclocal,&idxs));
82251e0482f5SStefano Zampini       }
82269566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2));
82279566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]));
82289566063dSJacob Faibussowitsch       /* PetscCall(ISView(isarray[i],0)); */
82296e683305SStefano Zampini     }
82306e683305SStefano Zampini     /* neumann boundaries */
82316e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
82329566063dSJacob Faibussowitsch       /* PetscCall(ISView(pcbddc->NeumannBoundariesLocal,0)); */
82339566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize));
82349566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs));
82359566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs));
82369566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs));
82379566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2));
82389566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]));
82399566063dSJacob Faibussowitsch       /* PetscCall(ISView(isarray[nisdofs],0)); */
82406e683305SStefano Zampini     }
82414f819b78SStefano Zampini     /* coordinates */
82424f819b78SStefano Zampini     if (pcbddc->corner_selected) {
82439566063dSJacob Faibussowitsch       PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners));
82449566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(corners,&tsize));
82459566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(corners,&idxs));
82469566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs));
824763a3b9bcSJacob Faibussowitsch       PetscCheck(tsize == nout,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping corners! %" PetscInt_FMT " != %" PetscInt_FMT,tsize,nout);
82489566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(corners,&idxs));
82499566063dSJacob Faibussowitsch       PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners));
82509566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2));
82519566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&corners));
82524f819b78SStefano Zampini     }
82539566063dSJacob Faibussowitsch     PetscCall(PetscFree(tidxs));
82549566063dSJacob Faibussowitsch     PetscCall(PetscFree(tidxs2));
82559566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&tmap));
82566e683305SStefano Zampini   } else {
82576e683305SStefano Zampini     nis = 0;
82586e683305SStefano Zampini     nisdofs = 0;
82596e683305SStefano Zampini     nisneu = 0;
826030368db7SStefano Zampini     nisvert = 0;
82616e683305SStefano Zampini     isarray = NULL;
82626e683305SStefano Zampini   }
82636e683305SStefano Zampini   /* destroy no longer needed map */
82649566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&coarse_islg));
82656e683305SStefano Zampini 
826657de7509SStefano Zampini   /* subassemble */
826757de7509SStefano Zampini   if (multilevel_allowed) {
82681ae86dd6SStefano Zampini     Vec       vp[1];
82691ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
827057de7509SStefano Zampini     PetscBool reuse,reuser;
82711ae86dd6SStefano Zampini 
827257de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
827357de7509SStefano Zampini     else reuse = PETSC_FALSE;
82741c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
82751ae86dd6SStefano Zampini     vp[0] = NULL;
82761ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
82779566063dSJacob Faibussowitsch       PetscCall(VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]));
82789566063dSJacob Faibussowitsch       PetscCall(VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE));
82799566063dSJacob Faibussowitsch       PetscCall(VecSetType(vp[0],VECSTANDARD));
82801ae86dd6SStefano Zampini       nvecs = 1;
82811ae86dd6SStefano Zampini 
82821ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
8283a198735bSStefano Zampini         Mat      B,loc_divudotp;
82841ae86dd6SStefano Zampini         Vec      v,p;
82851ae86dd6SStefano Zampini         IS       dummy;
82861ae86dd6SStefano Zampini         PetscInt np;
82871ae86dd6SStefano Zampini 
82889566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp));
82899566063dSJacob Faibussowitsch         PetscCall(MatGetSize(loc_divudotp,&np,NULL));
82909566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy));
82919566063dSJacob Faibussowitsch         PetscCall(MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B));
82929566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(B,&v,&p));
82939566063dSJacob Faibussowitsch         PetscCall(VecSet(p,1.));
82949566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(B,p,v));
82959566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&p));
82969566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&B));
82979566063dSJacob Faibussowitsch         PetscCall(VecGetArray(vp[0],&array));
82989566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec1_P,array));
82999566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P));
83009566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec1_P));
83019566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(vp[0],&array));
83029566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&dummy));
83039566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&v));
830474e2c79eSStefano Zampini       }
83051ae86dd6SStefano Zampini     }
83061ae86dd6SStefano Zampini     if (reuser) {
83079566063dSJacob Faibussowitsch       PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp));
830874e2c79eSStefano Zampini     } else {
83099566063dSJacob Faibussowitsch       PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray,nvecs,vp));
83101ae86dd6SStefano Zampini     }
83111ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
83121683a169SBarry Smith       PetscScalar       *arraym;
83131683a169SBarry Smith       const PetscScalar *arrayv;
83141ae86dd6SStefano Zampini       PetscInt          nl;
83159566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(vp[0],&nl));
83169566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp));
83179566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(coarsedivudotp,&arraym));
83189566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(vp[0],&arrayv));
83199566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(arraym,arrayv,nl));
83209566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(vp[0],&arrayv));
83219566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(coarsedivudotp,&arraym));
83229566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&vp[0]));
8323a198735bSStefano Zampini     } else {
83249566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp));
83251ae86dd6SStefano Zampini     }
83261ae86dd6SStefano Zampini   } else {
83279566063dSJacob Faibussowitsch     PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,0,NULL,0,NULL));
83286e683305SStefano Zampini   }
832957de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
833057de7509SStefano Zampini     if (!multilevel_allowed) {
83319566063dSJacob Faibussowitsch       PetscCall(MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat));
83326e683305SStefano Zampini     } else {
833357de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
833457de7509SStefano Zampini       if (coarse_mat_is) {
833528b400f6SJacob Faibussowitsch         PetscCheck(!coarse_mat,PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
83369566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)coarse_mat_is));
833757de7509SStefano Zampini         coarse_mat = coarse_mat_is;
833857de7509SStefano Zampini       }
8339779c1cceSStefano Zampini     }
8340779c1cceSStefano Zampini   }
83419566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&t_coarse_mat_is));
83429566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarse_mat_is));
83436e683305SStefano Zampini 
83446e683305SStefano Zampini   /* create local to global scatters for coarse problem */
834568457ee5SStefano Zampini   if (compute_vecs) {
83466e683305SStefano Zampini     PetscInt lrows;
83479566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->coarse_vec));
834857de7509SStefano Zampini     if (coarse_mat) {
83499566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(coarse_mat,&lrows,NULL));
83506e683305SStefano Zampini     } else {
83516e683305SStefano Zampini       lrows = 0;
83526e683305SStefano Zampini     }
83539566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec));
83549566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE));
83559566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcbddc->coarse_vec,coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD));
83569566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob));
83579566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob));
83586e683305SStefano Zampini   }
83599566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&coarse_is));
8360c8587f34SStefano Zampini 
8361f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
8362f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
8363f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
8364f9eb5b7dSStefano Zampini     coarse_pc_type  = PCBDDC;
8365f9eb5b7dSStefano Zampini   } else {
8366f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
8367f9eb5b7dSStefano Zampini     coarse_pc_type  = PCREDUNDANT;
8368c8587f34SStefano Zampini   }
8369c8587f34SStefano Zampini 
83706e683305SStefano Zampini   /* print some info if requested */
83716e683305SStefano Zampini   if (pcbddc->dbg_flag) {
83726e683305SStefano Zampini     if (!multilevel_allowed) {
83739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
83746e683305SStefano Zampini       if (multilevel_requested) {
837563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Not enough active processes on level %" PetscInt_FMT " (active processes %" PetscInt_FMT ", coarsening ratio %" PetscInt_FMT ")\n",pcbddc->current_level,active_procs,pcbddc->coarsening_ratio));
83766e683305SStefano Zampini       } else if (pcbddc->max_levels) {
837763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%" PetscInt_FMT ")\n",pcbddc->max_levels));
83786e683305SStefano Zampini       }
83799566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
83806e683305SStefano Zampini     }
83816e683305SStefano Zampini   }
83826e683305SStefano Zampini 
83831e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
83841e0482f5SStefano Zampini   coarseG = NULL;
83851e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
83861e0482f5SStefano Zampini     MPI_Comm ccomm;
83871e0482f5SStefano Zampini     if (coarse_mat) {
83881e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
83891e0482f5SStefano Zampini     } else {
83901e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
83911e0482f5SStefano Zampini     }
83929566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG));
83931e0482f5SStefano Zampini   }
83941e0482f5SStefano Zampini 
8395f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
839657de7509SStefano Zampini   if (coarse_mat) {
839728d58a37SPierre Jolivet     PetscBool   isredundant,isbddc,force,valid;
83986a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
8399*b94d7dedSBarry Smith     PetscBool   isset,issym,isher,isspd;
84007274672aSStefano Zampini 
84016e683305SStefano Zampini     if (pcbddc->dbg_flag) {
840257de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
84039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level));
84046e683305SStefano Zampini     }
8405f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8406312be037SStefano Zampini       char      prefix[256],str_level[16];
8407e604994aSStefano Zampini       size_t    len;
84081e0482f5SStefano Zampini 
84099566063dSJacob Faibussowitsch       PetscCall(KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp));
84109566063dSJacob Faibussowitsch       PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure));
84119566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1));
84129566063dSJacob Faibussowitsch       PetscCall(KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1));
84139566063dSJacob Faibussowitsch       PetscCall(KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat));
84149566063dSJacob Faibussowitsch       PetscCall(KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type));
84159566063dSJacob Faibussowitsch       PetscCall(KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE));
84169566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&pc_temp));
84171e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
84189566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,coarse_pc_type));
8419e604994aSStefano Zampini       /* prefix */
84209566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(prefix,""));
84219566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(str_level,""));
8422e604994aSStefano Zampini       if (!pcbddc->current_level) {
84239566063dSJacob Faibussowitsch         PetscCall(PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix)));
84249566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix)));
8425c8587f34SStefano Zampini       } else {
84269566063dSJacob Faibussowitsch         PetscCall(PetscStrlen(((PetscObject)pc)->prefix,&len));
8427312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8428312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
8429a126751eSBarry Smith         /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */
84309566063dSJacob Faibussowitsch         PetscCall(PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1));
84319566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level)));
84329566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(prefix,str_level,sizeof(prefix)));
8433e604994aSStefano Zampini       }
84349566063dSJacob Faibussowitsch       PetscCall(KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix));
84353e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
84369566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetLevel(pc_temp,pcbddc->current_level+1));
84379566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio));
84389566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetLevels(pc_temp,pcbddc->max_levels));
8439f9eb5b7dSStefano Zampini       /* allow user customization */
84409566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(pcbddc->coarse_ksp));
8441e569e4e1SStefano Zampini       /* get some info after set from options */
84429566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&pc_temp));
844328d58a37SPierre Jolivet       /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */
844428d58a37SPierre Jolivet       force = PETSC_FALSE;
84459566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL));
84469566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,""));
84479566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc));
844828d58a37SPierre Jolivet       if (multilevel_allowed && !force && !valid) {
8449e569e4e1SStefano Zampini         isbddc = PETSC_TRUE;
84509566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc_temp,PCBDDC));
84519566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetLevel(pc_temp,pcbddc->current_level+1));
84529566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio));
84539566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetLevels(pc_temp,pcbddc->max_levels));
84544f819b78SStefano Zampini         if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */
8455d0609cedSBarry Smith           PetscObjectOptionsBegin((PetscObject)pc_temp);
84569566063dSJacob Faibussowitsch           PetscCall((*pc_temp->ops->setfromoptions)(PetscOptionsObject,pc_temp));
84579566063dSJacob Faibussowitsch           PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pc_temp));
8458d0609cedSBarry Smith           PetscOptionsEnd();
84594f819b78SStefano Zampini           pc_temp->setfromoptionscalled++;
84604f819b78SStefano Zampini         }
8461e569e4e1SStefano Zampini       }
84623e3c6dadSStefano Zampini     }
84633e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
84649566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcbddc->coarse_ksp,&pc_temp));
84653e3c6dadSStefano Zampini     if (nisdofs) {
84669566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray));
84673e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
84689566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&isarray[i]));
84693e3c6dadSStefano Zampini       }
84703e3c6dadSStefano Zampini     }
84713e3c6dadSStefano Zampini     if (nisneu) {
84729566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]));
84739566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isarray[nisdofs]));
8474312be037SStefano Zampini     }
847530368db7SStefano Zampini     if (nisvert) {
84769566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]));
84779566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isarray[nis-1]));
847830368db7SStefano Zampini     }
84791baa6e33SBarry Smith     if (coarseG) PetscCall(PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE));
8480f9eb5b7dSStefano Zampini 
8481f9eb5b7dSStefano Zampini     /* get some info after set from options */
84829566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc));
84834f819b78SStefano Zampini 
8484b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8485b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
84869566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,coarse_pc_type));
8487f9eb5b7dSStefano Zampini     }
848828d58a37SPierre Jolivet     /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */
848928d58a37SPierre Jolivet     force = PETSC_FALSE;
84909566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL));
84919566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,""));
849228d58a37SPierre Jolivet     if (multilevel_requested && multilevel_allowed && !valid && !force) {
84939566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,PCBDDC));
8494b76f3995Sstefano_zampini     }
84959566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant));
84964f3a063dSStefano Zampini     if (isredundant) {
84974f3a063dSStefano Zampini       KSP inner_ksp;
84984f3a063dSStefano Zampini       PC  inner_pc;
84999326c5c6Sstefano_zampini 
85009566063dSJacob Faibussowitsch       PetscCall(PCRedundantGetKSP(pc_temp,&inner_ksp));
85019566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(inner_ksp,&inner_pc));
85024f3a063dSStefano Zampini     }
8503f9eb5b7dSStefano Zampini 
850457de7509SStefano Zampini     /* parameters which miss an API */
85059566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc));
850657de7509SStefano Zampini     if (isbddc) {
8507720d30f9SStefano Zampini       PC_BDDC*  pcbddc_coarse = (PC_BDDC*)pc_temp->data;
85087274672aSStefano Zampini 
8509720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
851057de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
8511e569e4e1SStefano Zampini       pcbddc_coarse->coarse_eqs_limit    = pcbddc->coarse_eqs_limit;
851227b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
851327b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8514a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8515a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8516a198735bSStefano Zampini         IS                     row,col;
8517a198735bSStefano Zampini         const PetscInt         *gidxs;
8518a198735bSStefano Zampini         PetscInt               n,st,M,N;
8519a198735bSStefano Zampini 
85209566063dSJacob Faibussowitsch         PetscCall(MatGetSize(coarsedivudotp,&n,NULL));
85219566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat)));
8522a198735bSStefano Zampini         st   = st-n;
85239566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row));
85249566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL));
85259566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(l2gmap,&n));
85269566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs));
85279566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col));
85289566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs));
85299566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingCreateIS(row,&rl2g));
85309566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingCreateIS(col,&cl2g));
85319566063dSJacob Faibussowitsch         PetscCall(ISGetSize(row,&M));
85329566063dSJacob Faibussowitsch         PetscCall(MatGetSize(coarse_mat,&N,NULL));
85339566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&row));
85349566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&col));
85359566063dSJacob Faibussowitsch         PetscCall(MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is));
85369566063dSJacob Faibussowitsch         PetscCall(MatSetType(coarsedivudotp_is,MATIS));
85379566063dSJacob Faibussowitsch         PetscCall(MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N));
85389566063dSJacob Faibussowitsch         PetscCall(MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g));
85399566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
85409566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
85419566063dSJacob Faibussowitsch         PetscCall(MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp));
85429566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&coarsedivudotp));
85439566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL));
85449566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&coarsedivudotp_is));
8545720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8546bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8547720d30f9SStefano Zampini       }
8548d4d8cf7bSStefano Zampini     }
85499881197aSStefano Zampini 
85503301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
85519566063dSJacob Faibussowitsch     PetscCall(MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE));
8552*b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pc->pmat,&isset,&issym));
8553*b94d7dedSBarry Smith     if (isset) PetscCall(MatSetOption(coarse_mat,MAT_SYMMETRIC,issym));
8554*b94d7dedSBarry Smith     PetscCall(MatIsHermitianKnown(pc->pmat,&isset,&isher));
8555*b94d7dedSBarry Smith     if (isset) PetscCall(MatSetOption(coarse_mat,MAT_HERMITIAN,isher));
8556*b94d7dedSBarry Smith     PetscCall(MatIsSPDKnown(pc->pmat,&isset,&isspd));
8557*b94d7dedSBarry Smith     if (isset) PetscCall(MatSetOption(coarse_mat,MAT_SPD,isspd));
8558*b94d7dedSBarry Smith 
855927b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
85609566063dSJacob Faibussowitsch       PetscCall(MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE));
856127b6a85dSStefano Zampini     }
85626e683305SStefano Zampini     /* set operators */
85639566063dSJacob Faibussowitsch     PetscCall(MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view"));
85649566063dSJacob Faibussowitsch     PetscCall(MatSetOptionsPrefix(coarse_mat,((PetscObject)pcbddc->coarse_ksp)->prefix));
85659566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat));
85661baa6e33SBarry Smith     if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level));
85676e683305SStefano Zampini   }
85689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarseG));
85699566063dSJacob Faibussowitsch   PetscCall(PetscFree(isarray));
8570b1ecc7b1SStefano Zampini #if 0
8571b9b85e73SStefano Zampini   {
8572b9b85e73SStefano Zampini     PetscViewer viewer;
8573b9b85e73SStefano Zampini     char filename[256];
8574b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
85759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer));
85769566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB));
85779566063dSJacob Faibussowitsch     PetscCall(MatView(coarse_mat,viewer));
85789566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
85799566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
8580b9b85e73SStefano Zampini   }
8581b9b85e73SStefano Zampini #endif
8582f9eb5b7dSStefano Zampini 
85834f819b78SStefano Zampini   if (corners) {
85844f819b78SStefano Zampini     Vec            gv;
85854f819b78SStefano Zampini     IS             is;
85864f819b78SStefano Zampini     const PetscInt *idxs;
85874f819b78SStefano Zampini     PetscInt       i,d,N,n,cdim = pcbddc->mat_graph->cdim;
85884f819b78SStefano Zampini     PetscScalar    *coords;
85894f819b78SStefano Zampini 
859028b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->mat_graph->cloc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing local coordinates");
85919566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcbddc->coarse_vec,&N));
85929566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(pcbddc->coarse_vec,&n));
85939566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec),&gv));
85949566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(gv,cdim));
85959566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(gv,n*cdim,N*cdim));
85969566063dSJacob Faibussowitsch     PetscCall(VecSetType(gv,VECSTANDARD));
85979566063dSJacob Faibussowitsch     PetscCall(VecSetFromOptions(gv));
85989566063dSJacob Faibussowitsch     PetscCall(VecSet(gv,PETSC_MAX_REAL)); /* we only propagate coordinates from vertices constraints */
85994f819b78SStefano Zampini 
86009566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is));
86019566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is,&n));
86029566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,&idxs));
86039566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n*cdim,&coords));
86044f819b78SStefano Zampini     for (i=0;i<n;i++) {
86054f819b78SStefano Zampini       for (d=0;d<cdim;d++) {
86064f819b78SStefano Zampini         coords[cdim*i+d] = pcbddc->mat_graph->coords[cdim*idxs[i]+d];
86074f819b78SStefano Zampini       }
86084f819b78SStefano Zampini     }
86099566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is,&idxs));
86109566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is));
86114f819b78SStefano Zampini 
86129566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(corners,&n));
86139566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(corners,&idxs));
86149566063dSJacob Faibussowitsch     PetscCall(VecSetValuesBlocked(gv,n,idxs,coords,INSERT_VALUES));
86159566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(corners,&idxs));
86169566063dSJacob Faibussowitsch     PetscCall(PetscFree(coords));
86179566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(gv));
86189566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(gv));
86199566063dSJacob Faibussowitsch     PetscCall(VecGetArray(gv,&coords));
86204f819b78SStefano Zampini     if (pcbddc->coarse_ksp) {
86214f819b78SStefano Zampini       PC        coarse_pc;
86224f819b78SStefano Zampini       PetscBool isbddc;
86234f819b78SStefano Zampini 
86249566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc));
86259566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc));
86264f819b78SStefano Zampini       if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */
86274f819b78SStefano Zampini         PetscReal *realcoords;
86284f819b78SStefano Zampini 
86299566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(gv,&n));
86304f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
86319566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(n,&realcoords));
86324f819b78SStefano Zampini         for (i=0;i<n;i++) realcoords[i] = PetscRealPart(coords[i]);
86334f819b78SStefano Zampini #else
86344f819b78SStefano Zampini         realcoords = coords;
86354f819b78SStefano Zampini #endif
86369566063dSJacob Faibussowitsch         PetscCall(PCSetCoordinates(coarse_pc,cdim,n/cdim,realcoords));
86374f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
86389566063dSJacob Faibussowitsch         PetscCall(PetscFree(realcoords));
86394f819b78SStefano Zampini #endif
86404f819b78SStefano Zampini       }
86414f819b78SStefano Zampini     }
86429566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(gv,&coords));
86439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&gv));
86444f819b78SStefano Zampini   }
86459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&corners));
86464f819b78SStefano Zampini 
864798a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
864898a51de6SStefano Zampini     Vec crhs,csol;
864904708bb6SStefano Zampini 
86509566063dSJacob Faibussowitsch     PetscCall(KSPGetSolution(pcbddc->coarse_ksp,&csol));
86519566063dSJacob Faibussowitsch     PetscCall(KSPGetRhs(pcbddc->coarse_ksp,&crhs));
8652f347579bSStefano Zampini     if (!csol) {
86539566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL));
8654f9eb5b7dSStefano Zampini     }
8655f347579bSStefano Zampini     if (!crhs) {
86569566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs)));
8657f347579bSStefano Zampini     }
8658b0f5fe93SStefano Zampini   }
86599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarsedivudotp));
8660b0f5fe93SStefano Zampini 
8661b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8662b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8663b0f5fe93SStefano Zampini 
86649566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->vec1_P,0.));
86654f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
86669566063dSJacob Faibussowitsch       PetscCall(VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES));
86674f1b2e48SStefano Zampini     }
86689566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcbddc->vec1_P));
86699566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcbddc->vec1_P));
86709566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD));
86719566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD));
8672b0f5fe93SStefano Zampini     if (coarse_mat) {
8673b0f5fe93SStefano Zampini       Vec         nullv;
8674b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8675b0f5fe93SStefano Zampini       PetscInt    nl;
8676b0f5fe93SStefano Zampini 
86779566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(coarse_mat,&nullv,NULL));
86789566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(nullv,&nl));
86799566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array));
86809566063dSJacob Faibussowitsch       PetscCall(VecGetArray(nullv,&array2));
86819566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(array2,array,nl));
86829566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(nullv,&array2));
86839566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array));
86849566063dSJacob Faibussowitsch       PetscCall(VecNormalize(nullv,NULL));
86859566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace));
86869566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&nullv));
8687b0f5fe93SStefano Zampini     }
8688b0f5fe93SStefano Zampini   }
86899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0));
8690b0f5fe93SStefano Zampini 
86919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0));
8692b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8693b0f5fe93SStefano Zampini     PetscBool ispreonly;
8694b0f5fe93SStefano Zampini 
8695b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8696b0f5fe93SStefano Zampini       PetscBool isnull;
86977c625d9fSStefano Zampini 
86989566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull));
86991baa6e33SBarry Smith       if (isnull) PetscCall(MatSetNullSpace(coarse_mat,CoarseNullSpace));
8700bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8701b0f5fe93SStefano Zampini     }
8702b0f5fe93SStefano Zampini     /* setup coarse ksp */
87039566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcbddc->coarse_ksp));
8704cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
87059566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly));
87066e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) {
8707c8587f34SStefano Zampini       KSP       check_ksp;
87082b510759SStefano Zampini       KSPType   check_ksp_type;
8709c8587f34SStefano Zampini       PC        check_pc;
87106e683305SStefano Zampini       Vec       check_vec,coarse_vec;
87116a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
87122b510759SStefano Zampini       PetscInt  its;
87136e683305SStefano Zampini       PetscBool compute_eigs;
87146e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
87156e683305SStefano Zampini       PetscInt  neigs;
87168e185a42SStefano Zampini       const char *prefix;
8717c8587f34SStefano Zampini 
87182b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
87199566063dSJacob Faibussowitsch       PetscCall(KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp));
87209566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)check_ksp,(PetscObject)pcbddc->coarse_ksp,0));
87219566063dSJacob Faibussowitsch       PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,PETSC_FALSE));
87229566063dSJacob Faibussowitsch       PetscCall(KSPSetOperators(check_ksp,coarse_mat,coarse_mat));
87239566063dSJacob Faibussowitsch       PetscCall(KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size));
8724e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
87259566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(check_ksp,&check_pc));
87269566063dSJacob Faibussowitsch       PetscCall(PCSetType(check_pc,PCNONE));
87272b510759SStefano Zampini       if (ispreonly) {
87282b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
87296e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
87302b510759SStefano Zampini       } else {
8731cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
87326e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8733c8587f34SStefano Zampini       }
87349566063dSJacob Faibussowitsch       PetscCall(KSPSetType(check_ksp,check_ksp_type));
87359566063dSJacob Faibussowitsch       PetscCall(KSPSetComputeSingularValues(check_ksp,compute_eigs));
87369566063dSJacob Faibussowitsch       PetscCall(KSPSetComputeEigenvalues(check_ksp,compute_eigs));
87379566063dSJacob Faibussowitsch       PetscCall(KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1));
87389566063dSJacob Faibussowitsch       PetscCall(KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix));
87399566063dSJacob Faibussowitsch       PetscCall(KSPSetOptionsPrefix(check_ksp,prefix));
87409566063dSJacob Faibussowitsch       PetscCall(KSPAppendOptionsPrefix(check_ksp,"check_"));
87419566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(check_ksp));
87429566063dSJacob Faibussowitsch       PetscCall(KSPSetUp(check_ksp));
87439566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&check_pc));
87449566063dSJacob Faibussowitsch       PetscCall(KSPSetPC(check_ksp,check_pc));
8745c8587f34SStefano Zampini       /* create random vec */
87469566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(coarse_mat,&coarse_vec,&check_vec));
87479566063dSJacob Faibussowitsch       PetscCall(VecSetRandom(check_vec,NULL));
87489566063dSJacob Faibussowitsch       PetscCall(MatMult(coarse_mat,check_vec,coarse_vec));
8749c8587f34SStefano Zampini       /* solve coarse problem */
87509566063dSJacob Faibussowitsch       PetscCall(KSPSolve(check_ksp,coarse_vec,coarse_vec));
87519566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(check_ksp,pc,coarse_vec));
8752cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
87536e683305SStefano Zampini       if (compute_eigs) {
87549566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(pcbddc->coarse_size+1,&eigs_r));
87559566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(pcbddc->coarse_size+1,&eigs_c));
87569566063dSJacob Faibussowitsch         PetscCall(KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs));
87571ae86dd6SStefano Zampini         if (neigs) {
87586e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
87596e683305SStefano Zampini           lambda_min = eigs_r[0];
87606e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
87612701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
87629566063dSJacob Faibussowitsch               PetscCall(KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min));
87639566063dSJacob Faibussowitsch               PetscCall(KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min)));
8764cbcc2c2aSStefano Zampini             }
8765c8587f34SStefano Zampini           }
8766c8587f34SStefano Zampini         }
87671ae86dd6SStefano Zampini       }
8768cbcc2c2aSStefano Zampini 
8769c8587f34SStefano Zampini       /* check coarse problem residual error */
87706e683305SStefano Zampini       if (pcbddc->dbg_flag) {
87716e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
87729566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1)));
87739566063dSJacob Faibussowitsch         PetscCall(VecAXPY(check_vec,-1.0,coarse_vec));
87749566063dSJacob Faibussowitsch         PetscCall(VecNorm(check_vec,NORM_INFINITY,&infty_error));
87759566063dSJacob Faibussowitsch         PetscCall(MatMult(coarse_mat,check_vec,coarse_vec));
87769566063dSJacob Faibussowitsch         PetscCall(VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error));
87779566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates));
87789566063dSJacob Faibussowitsch         PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer));
87799566063dSJacob Faibussowitsch         PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer));
878063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",(double)infty_error));
878163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",(double)abs_infty_error));
8782b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
87839566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n"));
8784b0f5fe93SStefano Zampini         }
87856e683305SStefano Zampini         if (compute_eigs) {
87866e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8787b03ebc13SStefano Zampini           KSPConvergedReason reason;
87889566063dSJacob Faibussowitsch           PetscCall(KSPGetType(check_ksp,&check_ksp_type));
87899566063dSJacob Faibussowitsch           PetscCall(KSPGetIterationNumber(check_ksp,&its));
87909566063dSJacob Faibussowitsch           PetscCall(KSPGetConvergedReason(check_ksp,&reason));
87919566063dSJacob Faibussowitsch           PetscCall(KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s));
879263a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem eigenvalues (estimated with %" PetscInt_FMT " iterations of %s, conv reason %d): %1.6e %1.6e (%1.6e %1.6e)\n",its,check_ksp_type,reason,(double)lambda_min,(double)lambda_max,(double)lambda_min_s,(double)lambda_max_s));
87936e683305SStefano Zampini           for (i=0;i<neigs;i++) {
879463a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",(double)eigs_r[i],(double)eigs_c[i]));
8795c8587f34SStefano Zampini           }
87966e683305SStefano Zampini         }
87979566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(dbg_viewer));
87989566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1)));
87996e683305SStefano Zampini       }
88009566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&check_vec));
88019566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&coarse_vec));
88029566063dSJacob Faibussowitsch       PetscCall(KSPDestroy(&check_ksp));
88036e683305SStefano Zampini       if (compute_eigs) {
88049566063dSJacob Faibussowitsch         PetscCall(PetscFree(eigs_r));
88059566063dSJacob Faibussowitsch         PetscCall(PetscFree(eigs_c));
8806c8587f34SStefano Zampini       }
88076e683305SStefano Zampini     }
88086e683305SStefano Zampini   }
88099566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&CoarseNullSpace));
8810cbcc2c2aSStefano Zampini   /* print additional info */
8811cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
88126e683305SStefano Zampini     /* waits until all processes reaches this point */
88139566063dSJacob Faibussowitsch     PetscCall(PetscBarrier((PetscObject)pc));
881463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %" PetscInt_FMT "\n",pcbddc->current_level));
88159566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
8816cbcc2c2aSStefano Zampini   }
8817cbcc2c2aSStefano Zampini 
88182b510759SStefano Zampini   /* free memory */
88199566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarse_mat));
88209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0));
8821c8587f34SStefano Zampini   PetscFunctionReturn(0);
8822c8587f34SStefano Zampini }
8823674ae819SStefano Zampini 
8824f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8825f34684f1SStefano Zampini {
8826f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8827f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8828f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8829dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8830dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
883173be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8832dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8833f34684f1SStefano Zampini 
8834f34684f1SStefano Zampini   PetscFunctionBegin;
8835f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
883608401ef6SPierre Jolivet   PetscCheck(!pcbddc->local_primal_size || pcbddc->local_primal_ref_node,PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
88379566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n));
88389566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset));
88399566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&subset_n));
88409566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult));
88419566063dSJacob Faibussowitsch   PetscCall(ISRenumber(subset,subset_mult,&coarse_size,&subset_n));
88429566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&subset));
88439566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&subset_mult));
88449566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(subset_n,&local_size));
884563a3b9bcSJacob Faibussowitsch   PetscCheck(local_size == pcbddc->local_primal_size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %" PetscInt_FMT " != %" PetscInt_FMT,local_size,pcbddc->local_primal_size);
88469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(local_size,&local_primal_indices));
88479566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(subset_n,&t_local_primal_indices));
88489566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(local_primal_indices,t_local_primal_indices,local_size));
88499566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(subset_n,&t_local_primal_indices));
88509566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&subset_n));
8851f34684f1SStefano Zampini 
8852f34684f1SStefano Zampini   /* check numbering */
8853f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8854019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8855dc456d91SStefano Zampini     PetscInt    i;
8856b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8857f34684f1SStefano Zampini 
88589566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
88599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
88609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n"));
88619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
8862019a44ceSStefano Zampini     /* counter */
88639566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_global,0.0));
88649566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_N,1.0));
88659566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
88669566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
88679566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
88689566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
88699566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_N,0.0));
8870f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
88719566063dSJacob Faibussowitsch       PetscCall(VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES));
8872f34684f1SStefano Zampini     }
88739566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec1_N));
88749566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec1_N));
88759566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_global,0.0));
88769566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
88779566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
88789566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
88799566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
88809566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcis->vec1_N,&array));
88819566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcis->vec2_N,&array2));
8882f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8883019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
88842c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
888575c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8886b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
88879566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi));
888863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %" PetscInt_FMT " (gid %" PetscInt_FMT ") owned by %" PetscInt_FMT " processes instead of %" PetscInt_FMT "!\n",PetscGlobalRank,i,gi,owned,neigh));
8889f34684f1SStefano Zampini       }
8890f34684f1SStefano Zampini     }
88919566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcis->vec2_N,&array2));
88921c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
88939566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
8894f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8895f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8896f34684f1SStefano Zampini     }
88979566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcis->vec1_N,&array));
88989566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_global,0.0));
88999566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
89009566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
89019566063dSJacob Faibussowitsch     PetscCall(VecSum(pcis->vec1_global,&coarsesum));
890263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %" PetscInt_FMT " (%lf)\n",coarse_size,(double)PetscRealPart(coarsesum)));
8903b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8904ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8905ca8b9ea9SStefano Zampini 
89069566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcbddc->local_primal_size,&gidxs));
89079566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs));
89089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n"));
89099566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
89109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank));
8911f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
891263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%" PetscInt_FMT "]=%" PetscInt_FMT " (%" PetscInt_FMT ",%" PetscInt_FMT ")\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i],gidxs[i]));
8913f34684f1SStefano Zampini       }
89149566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
89159566063dSJacob Faibussowitsch       PetscCall(PetscFree(gidxs));
8916f34684f1SStefano Zampini     }
89179566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
89189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
891928b400f6SJacob Faibussowitsch     PetscCheck(!set_error_reduced,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8920f34684f1SStefano Zampini   }
89216080607fSStefano Zampini 
8922f34684f1SStefano Zampini   /* get back data */
8923f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8924f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8925674ae819SStefano Zampini   PetscFunctionReturn(0);
8926674ae819SStefano Zampini }
8927674ae819SStefano Zampini 
8928a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8929e456f2a8SStefano Zampini {
8930e456f2a8SStefano Zampini   IS             localis_t;
8931a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8932e456f2a8SStefano Zampini   PetscScalar    *vals;
8933e456f2a8SStefano Zampini 
8934e456f2a8SStefano Zampini   PetscFunctionBegin;
8935a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
89369566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(globalis,&lsize));
89379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(lsize,&vals));
8938e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
89399566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(globalis,(const PetscInt**)&idxs));
89409566063dSJacob Faibussowitsch   PetscCall(VecSet(gwork,0.0));
89419566063dSJacob Faibussowitsch   PetscCall(VecSet(lwork,0.0));
89421035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
89439566063dSJacob Faibussowitsch     PetscCall(VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE));
89449566063dSJacob Faibussowitsch     PetscCall(VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES));
89451035eff8SStefano Zampini   }
89469566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(gwork));
89479566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(globalis,(const PetscInt**)&idxs));
89489566063dSJacob Faibussowitsch   PetscCall(PetscFree(vals));
89499566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(gwork));
8950a7dc3881SStefano Zampini   /* now compute set in local ordering */
89519566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD));
89529566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD));
89539566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(lwork,(const PetscScalar**)&vals));
89549566063dSJacob Faibussowitsch   PetscCall(VecGetSize(lwork,&n));
8955a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8956ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8957e456f2a8SStefano Zampini       lsize++;
8958e456f2a8SStefano Zampini     }
8959e456f2a8SStefano Zampini   }
89609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(lsize,&idxs));
8961a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8962ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8963e456f2a8SStefano Zampini       idxs[lsize++] = i;
8964e456f2a8SStefano Zampini     }
8965e456f2a8SStefano Zampini   }
89669566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(lwork,(const PetscScalar**)&vals));
89679566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t));
8968e456f2a8SStefano Zampini   *localis = localis_t;
8969e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8970e456f2a8SStefano Zampini }
8971906d46d4SStefano Zampini 
897232fe681dSStefano Zampini PetscErrorCode PCBDDCComputeFakeChange(PC pc, PetscBool constraints, PCBDDCGraph graph, PCBDDCSubSchurs schurs, Mat *change, IS *change_primal, IS *change_primal_mult, PetscBool *change_with_qr)
89737c625d9fSStefano Zampini {
89747c625d9fSStefano Zampini   PC_IS   *pcis = (PC_IS*)pc->data;
89757c625d9fSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
89767c625d9fSStefano Zampini   PC_IS   *pcisf;
89777c625d9fSStefano Zampini   PC_BDDC *pcbddcf;
89787c625d9fSStefano Zampini   PC      pcf;
89797c625d9fSStefano Zampini 
89807c625d9fSStefano Zampini   PetscFunctionBegin;
89817c625d9fSStefano Zampini   PetscCall(PCCreate(PetscObjectComm((PetscObject)pc),&pcf));
89827c625d9fSStefano Zampini   PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)pcf));
89837c625d9fSStefano Zampini   PetscCall(PCSetOperators(pcf,pc->mat,pc->pmat));
89847c625d9fSStefano Zampini   PetscCall(PCSetType(pcf,PCBDDC));
89857c625d9fSStefano Zampini 
89867c625d9fSStefano Zampini   pcisf   = (PC_IS*)pcf->data;
898732fe681dSStefano Zampini   pcbddcf = (PC_BDDC*)pcf->data;
898832fe681dSStefano Zampini 
89897c625d9fSStefano Zampini   pcisf->is_B_local = pcis->is_B_local;
89907c625d9fSStefano Zampini   pcisf->vec1_N     = pcis->vec1_N;
89917c625d9fSStefano Zampini   pcisf->BtoNmap    = pcis->BtoNmap;
89927c625d9fSStefano Zampini   pcisf->n          = pcis->n;
89937c625d9fSStefano Zampini   pcisf->n_B        = pcis->n_B;
89947c625d9fSStefano Zampini 
89957c625d9fSStefano Zampini   PetscCall(PetscFree(pcbddcf->mat_graph));
899632fe681dSStefano Zampini   PetscCall(PetscFree(pcbddcf->sub_schurs));
89977c625d9fSStefano Zampini   pcbddcf->mat_graph             = graph ? graph : pcbddc->mat_graph;
899832fe681dSStefano Zampini   pcbddcf->sub_schurs            = schurs;
899932fe681dSStefano Zampini   pcbddcf->adaptive_selection    = schurs ? PETSC_TRUE : PETSC_FALSE;
900032fe681dSStefano Zampini   pcbddcf->adaptive_threshold[0] = pcbddc->adaptive_threshold[0];
900132fe681dSStefano Zampini   pcbddcf->adaptive_threshold[1] = pcbddc->adaptive_threshold[1];
900232fe681dSStefano Zampini   pcbddcf->adaptive_nmin         = pcbddc->adaptive_nmin;
900332fe681dSStefano Zampini   pcbddcf->adaptive_nmax         = pcbddc->adaptive_nmax;
90047c625d9fSStefano Zampini   pcbddcf->use_faces             = PETSC_TRUE;
900532fe681dSStefano Zampini   pcbddcf->use_change_of_basis   = (PetscBool)!constraints;
900632fe681dSStefano Zampini   pcbddcf->use_change_on_faces   = (PetscBool)!constraints;
900732fe681dSStefano Zampini   pcbddcf->use_qr_single         = (PetscBool)!constraints;
90087c625d9fSStefano Zampini   pcbddcf->fake_change           = PETSC_TRUE;
900932fe681dSStefano Zampini   pcbddcf->dbg_flag              = pcbddc->dbg_flag;
901032fe681dSStefano Zampini 
901132fe681dSStefano Zampini   PetscCall(PCBDDCAdaptiveSelection(pcf));
90127c625d9fSStefano Zampini   PetscCall(PCBDDCConstraintsSetUp(pcf));
90137c625d9fSStefano Zampini 
90147c625d9fSStefano Zampini   *change = pcbddcf->ConstraintMatrix;
90157c625d9fSStefano Zampini   if (change_primal) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat),pcbddcf->local_primal_size_cc,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,change_primal));
90167c625d9fSStefano Zampini   if (change_primal_mult) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat),pcbddcf->local_primal_size_cc,pcbddcf->local_primal_ref_mult,PETSC_COPY_VALUES,change_primal_mult));
90177c625d9fSStefano Zampini   if (change_with_qr) *change_with_qr = pcbddcf->use_qr_single;
90187c625d9fSStefano Zampini 
901932fe681dSStefano Zampini   if (schurs) pcbddcf->sub_schurs = NULL;
90207c625d9fSStefano Zampini   pcbddcf->ConstraintMatrix       = NULL;
902132fe681dSStefano Zampini   pcbddcf->mat_graph              = NULL;
902232fe681dSStefano Zampini   pcisf->is_B_local               = NULL;
902332fe681dSStefano Zampini   pcisf->vec1_N                   = NULL;
902432fe681dSStefano Zampini   pcisf->BtoNmap                  = NULL;
90257c625d9fSStefano Zampini   PetscCall(PCDestroy(&pcf));
90267c625d9fSStefano Zampini   PetscFunctionReturn(0);
90277c625d9fSStefano Zampini }
90287c625d9fSStefano Zampini 
902908122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
9030b96c3477SStefano Zampini {
9031a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9032b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9033b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
9034a64f4aa4SStefano Zampini   Mat                 S_j;
9035b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
9036b96c3477SStefano Zampini   PetscBool           free_used_adj;
9037b96c3477SStefano Zampini 
9038b96c3477SStefano Zampini   PetscFunctionBegin;
90399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0));
9040b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
9041b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
904208122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
9043b96c3477SStefano Zampini     used_xadj = NULL;
9044b96c3477SStefano Zampini     used_adjncy = NULL;
9045b96c3477SStefano Zampini   } else {
904608122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
904708122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
904808122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
904908122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
9050b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
9051b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
9052b96c3477SStefano Zampini     } else {
90532fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
9054b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
9055b96c3477SStefano Zampini       PetscInt       nvtxs;
9056b96c3477SStefano Zampini 
90579566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row));
90582fffb893SStefano Zampini       if (flg_row) {
90599566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy));
90609566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(used_xadj,xadj,nvtxs+1));
90619566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(used_adjncy,adjncy,xadj[nvtxs]));
9062b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
90632fffb893SStefano Zampini       } else {
90642fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
90652fffb893SStefano Zampini         used_xadj = NULL;
90662fffb893SStefano Zampini         used_adjncy = NULL;
90672fffb893SStefano Zampini       }
90689566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row));
9069b96c3477SStefano Zampini     }
9070b96c3477SStefano Zampini   }
9071d5574798SStefano Zampini 
9072d5574798SStefano Zampini   /* setup sub_schurs data */
90739566063dSJacob Faibussowitsch   PetscCall(MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j));
9074df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
9075df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
90769566063dSJacob Faibussowitsch     PetscCall(MatSchurComplementSetKSP(S_j,pcbddc->ksp_D));
90779566063dSJacob Faibussowitsch     PetscCall(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));
9078a64f4aa4SStefano Zampini   } else {
907972b8c272SStefano Zampini     Mat       change = NULL;
90809d54b7f4SStefano Zampini     Vec       scaling = NULL;
9081111315fdSstefano_zampini     IS        change_primal = NULL, iP;
9082111315fdSstefano_zampini     PetscInt  benign_n;
9083111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
90847ebab0bbSStefano Zampini     PetscBool need_change = PETSC_FALSE;
9085111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
9086a3df083aSStefano Zampini 
90875feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
90885feab87aSStefano Zampini       PetscInt n_vertices;
90895feab87aSStefano Zampini 
90909566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(sub_schurs->is_vertices,&n_vertices));
90912034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
90925feab87aSStefano Zampini     }
9093a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
9094a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
9095ca92afb2SStefano Zampini     } else {
9096a3df083aSStefano Zampini       benign_n = 0;
9097ca92afb2SStefano Zampini     }
9098b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
9099b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
9100b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
910172b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
910222db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
91031c2dc1cbSBarry Smith       PetscCall(MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
910422db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
9105b7ab4a40SStefano Zampini     }
91067c625d9fSStefano Zampini     /* If the user defines additional constraints, we import them here */
9107b7ab4a40SStefano Zampini     if (need_change) {
910828b400f6SJacob Faibussowitsch       PetscCheck(!pcbddc->sub_schurs_rebuild,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
910932fe681dSStefano Zampini       PetscCall(PCBDDCComputeFakeChange(pc,PETSC_FALSE,NULL,NULL,&change,&change_primal,NULL,&sub_schurs->change_with_qr));
9110b9be95fcSstefano_zampini 
911188c03ad3SStefano Zampini     }
91129d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
9113111315fdSstefano_zampini 
91149566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP));
9115111315fdSstefano_zampini     if (iP) {
9116d0609cedSBarry Smith       PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");
91179566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL));
9118d0609cedSBarry Smith       PetscOptionsEnd();
9119111315fdSstefano_zampini     }
9120111315fdSstefano_zampini     if (discrete_harmonic) {
9121111315fdSstefano_zampini       Mat A;
91229566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A));
91239566063dSJacob Faibussowitsch       PetscCall(MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL));
91249566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP));
91259566063dSJacob Faibussowitsch       PetscCall(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));
91269566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A));
9127111315fdSstefano_zampini     } else {
91289566063dSJacob Faibussowitsch       PetscCall(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));
9129111315fdSstefano_zampini     }
91309566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&change));
91319566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&change_primal));
9132ca92afb2SStefano Zampini   }
91339566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_j));
9134b96c3477SStefano Zampini 
9135b96c3477SStefano Zampini   /* free adjacency */
91361baa6e33SBarry Smith   if (free_used_adj) PetscCall(PetscFree2(used_xadj,used_adjncy));
91379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0));
9138b96c3477SStefano Zampini   PetscFunctionReturn(0);
9139b96c3477SStefano Zampini }
9140b96c3477SStefano Zampini 
914108122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
9142b96c3477SStefano Zampini {
9143b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9144b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9145b96c3477SStefano Zampini   PCBDDCGraph         graph;
9146b96c3477SStefano Zampini 
9147b96c3477SStefano Zampini   PetscFunctionBegin;
9148b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
914908122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
91503301b35fSStefano Zampini     IS       verticesIS,verticescomm;
91513301b35fSStefano Zampini     PetscInt vsize,*idxs;
9152b96c3477SStefano Zampini 
91539566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS));
91549566063dSJacob Faibussowitsch     PetscCall(ISGetSize(verticesIS,&vsize));
91559566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(verticesIS,(const PetscInt**)&idxs));
91569566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm));
91579566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(verticesIS,(const PetscInt**)&idxs));
91589566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS));
91599566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphCreate(&graph));
91609566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount));
91619566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm));
91629566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&verticescomm));
91639566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphComputeConnectedComponents(graph));
9164b96c3477SStefano Zampini   } else {
9165b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
9166b96c3477SStefano Zampini   }
9167e4d548c7SStefano Zampini   /* print some info */
91685c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
9169e4d548c7SStefano Zampini     IS       vertices;
9170e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
91719566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer));
91729566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices));
91739566063dSJacob Faibussowitsch     PetscCall(ISGetSize(vertices,&nv));
91749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
91759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n"));
917663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices));
917763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges));
917863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces));
91799566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
91809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
91819566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices));
9182e4d548c7SStefano Zampini   }
9183b96c3477SStefano Zampini 
9184b96c3477SStefano Zampini   /* sub_schurs init */
9185b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
91869566063dSJacob Faibussowitsch     PetscCall(PCBDDCSubSchursCreate(&pcbddc->sub_schurs));
9187b334f244SStefano Zampini   }
918832fe681dSStefano Zampini   PetscCall(PCBDDCSubSchursInit(pcbddc->sub_schurs,((PetscObject)pc)->prefix,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_rebuild,PETSC_FALSE));
9189a64f4aa4SStefano Zampini 
9190b96c3477SStefano Zampini   /* free graph struct */
919108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
91929566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphDestroy(&graph));
9193b96c3477SStefano Zampini   }
9194b96c3477SStefano Zampini   PetscFunctionReturn(0);
9195b96c3477SStefano Zampini }
9196fa34dd3eSStefano Zampini 
9197fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
9198fa34dd3eSStefano Zampini {
9199fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9200fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9201fa34dd3eSStefano Zampini 
9202fa34dd3eSStefano Zampini   PetscFunctionBegin;
9203fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
9204fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
92054f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
9206fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
92074f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
920875c01103SStefano Zampini     PetscReal      norm;
9209fa34dd3eSStefano Zampini     PetscInt       i;
9210fa34dd3eSStefano Zampini 
9211fa34dd3eSStefano Zampini     /* B0 and B0_B */
9212fa34dd3eSStefano Zampini     if (zerodiag) {
9213fa34dd3eSStefano Zampini       IS       dummy;
9214fa34dd3eSStefano Zampini 
92159566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy));
92169566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B));
92179566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(B0_B,NULL,&dummy_vec));
92189566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dummy));
9219fa34dd3eSStefano Zampini     }
9220fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
92219566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcbddc->vec1_P,&vec_scale_P));
92229566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->vec1_P,1.0));
92239566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD));
92249566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD));
92259566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE));
92269566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE));
92279566063dSJacob Faibussowitsch     PetscCall(VecReciprocal(vec_scale_P));
9228fa34dd3eSStefano Zampini     /* S_j */
92299566063dSJacob Faibussowitsch     PetscCall(MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j));
92309566063dSJacob Faibussowitsch     PetscCall(MatSchurComplementSetKSP(S_j,pcbddc->ksp_D));
9231fa34dd3eSStefano Zampini 
9232fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
92339566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(pcis->vec1_N,NULL));
9234fa34dd3eSStefano Zampini     /* continuous in primal space */
92359566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(pcbddc->coarse_vec,NULL));
92369566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE));
92379566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE));
92389566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcbddc->vec1_P,&array));
92399566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(pcbddc->benign_n,&p0_check));
92404f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
92419566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES));
92429566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcbddc->vec1_P,&array));
92439566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec1_N));
92449566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec1_N));
92459566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD));
92469566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD));
92479566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec2_B,&vec_check_B));
92489566063dSJacob Faibussowitsch     PetscCall(VecCopy(pcis->vec2_B,vec_check_B));
9249fa34dd3eSStefano Zampini 
9250fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
9251fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
9252fa34dd3eSStefano Zampini     /* local with Schur */
92539566063dSJacob Faibussowitsch     PetscCall(MatMult(S_j,pcis->vec2_B,pcis->vec1_B));
9254fa34dd3eSStefano Zampini     if (zerodiag) {
92559566063dSJacob Faibussowitsch       PetscCall(VecGetArray(dummy_vec,&array));
92564f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
92579566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(dummy_vec,&array));
92589566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B));
9259fa34dd3eSStefano Zampini     }
9260fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
92619566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
92629566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
92639566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcis->vec1_N,&array));
92649566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcbddc->vec1_P,&array2));
9265fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
92669566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcbddc->vec1_P,&array2));
92679566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcis->vec1_N,&array));
92689566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->coarse_vec,0.));
92699566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD));
92709566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD));
92719566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE));
92729566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE));
92739566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcbddc->vec1_P,&array));
9274fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
92759566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P));
92769566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES));
92779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcbddc->vec1_P,&array));
92789566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec1_N));
92799566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec1_N));
92809566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
92819566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
9282fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
9283fa34dd3eSStefano Zampini     if (zerodiag) {
92849566063dSJacob Faibussowitsch       PetscCall(MatMult(B0_B,pcis->vec2_B,dummy_vec));
92859566063dSJacob Faibussowitsch       PetscCall(VecGetArray(dummy_vec,&array));
92864f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
92879566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(dummy_vec,&array));
9288fa34dd3eSStefano Zampini     }
9289fa34dd3eSStefano Zampini     /* BDDC */
92909566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_D,0.));
92919566063dSJacob Faibussowitsch     PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE));
9292fa34dd3eSStefano Zampini 
92939566063dSJacob Faibussowitsch     PetscCall(VecCopy(pcis->vec1_B,pcis->vec2_B));
92949566063dSJacob Faibussowitsch     PetscCall(VecAXPY(pcis->vec1_B,-1.0,vec_check_B));
92959566063dSJacob Faibussowitsch     PetscCall(VecNorm(pcis->vec1_B,NORM_INFINITY,&norm));
929663a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,(double)norm));
92974f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
929863a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%" PetscInt_FMT "] error is %1.4e\n",PetscGlobalRank,i,(double)PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i])));
9299fa34dd3eSStefano Zampini     }
93009566063dSJacob Faibussowitsch     PetscCall(PetscFree(p0_check));
93019566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vec_scale_P));
93029566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vec_check_B));
93039566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&dummy_vec));
93049566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&S_j));
93059566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B0_B));
9306fa34dd3eSStefano Zampini   }
9307fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
9308fa34dd3eSStefano Zampini }
93091e0482f5SStefano Zampini 
93101e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
93111e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
93121e0482f5SStefano Zampini {
93131e0482f5SStefano Zampini   Mat            At;
93141e0482f5SStefano Zampini   IS             rows;
93151e0482f5SStefano Zampini   PetscInt       rst,ren;
93161e0482f5SStefano Zampini   PetscLayout    rmap;
93171e0482f5SStefano Zampini 
93181e0482f5SStefano Zampini   PetscFunctionBegin;
93191e0482f5SStefano Zampini   rst = ren = 0;
93201e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
93219566063dSJacob Faibussowitsch     PetscCall(PetscLayoutCreate(ccomm,&rmap));
93229566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetSize(rmap,A->rmap->N));
93239566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetBlockSize(rmap,1));
93249566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp(rmap));
93259566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetRange(rmap,&rst,&ren));
93261e0482f5SStefano Zampini   }
93279566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows));
93289566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At));
93299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&rows));
93301e0482f5SStefano Zampini 
93311e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
93321e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
93331e0482f5SStefano Zampini     IS         from,to;
93341e0482f5SStefano Zampini     Vec        gvec;
93351e0482f5SStefano Zampini     PetscInt   lsize;
93361e0482f5SStefano Zampini 
93379566063dSJacob Faibussowitsch     PetscCall(MatCreate(ccomm,B));
93389566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N));
93399566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B,MATAIJ));
93409566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&((*B)->rmap)));
93419566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp((*B)->cmap));
93421e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
93431e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
93449566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(ccomm,&b->size));
93459566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(ccomm,&b->rank));
93469566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)a->A));
93479566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)a->B));
93481e0482f5SStefano Zampini     b->A = a->A;
93491e0482f5SStefano Zampini     b->B = a->B;
93501e0482f5SStefano Zampini 
93511e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
93521e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
93530a545947SLisandro Dalcin     b->rowindices      = NULL;
93540a545947SLisandro Dalcin     b->rowvalues       = NULL;
93551e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
93561e0482f5SStefano Zampini 
93571e0482f5SStefano Zampini     (*B)->rmap         = rmap;
93581e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
93591e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
93601e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
93611e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
93621e0482f5SStefano Zampini 
93631e0482f5SStefano Zampini     if (a->colmap) {
93641e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
93659566063dSJacob Faibussowitsch       PetscCall(PetscTableCreateCopy(a->colmap,&b->colmap));
93661e0482f5SStefano Zampini #else
93679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(At->cmap->N,&b->colmap));
93689566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt)));
93699566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(b->colmap,a->colmap,At->cmap->N));
93701e0482f5SStefano Zampini #endif
93710a545947SLisandro Dalcin     } else b->colmap = NULL;
93721e0482f5SStefano Zampini     if (a->garray) {
93731e0482f5SStefano Zampini       PetscInt len;
93741e0482f5SStefano Zampini       len  = a->B->cmap->n;
93759566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(len+1,&b->garray));
93769566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt)));
93779566063dSJacob Faibussowitsch       if (len) PetscCall(PetscArraycpy(b->garray,a->garray,len));
93780a545947SLisandro Dalcin     } else b->garray = NULL;
93791e0482f5SStefano Zampini 
93809566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)a->lvec));
93811e0482f5SStefano Zampini     b->lvec = a->lvec;
93829566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec));
93831e0482f5SStefano Zampini 
93841e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
93859566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(b->lvec,&lsize));
93869566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from));
93879566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to));
93889566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(*B,&gvec,NULL));
93899566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx));
93909566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx));
93919566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&from));
93929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&to));
93939566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&gvec));
93941e0482f5SStefano Zampini   }
93959566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&At));
93961e0482f5SStefano Zampini   PetscFunctionReturn(0);
93971e0482f5SStefano Zampini }
9398