xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 5e5bbd0a99ea6ef6b187abb9b4a6405ccdf6db1e)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2*5e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h>
3*5e5bbd0aSStefano 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   }
692c2151214SStefano Zampini   if (fl2g) {
6939566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(fl2g,cum,marks,marks));
694c2151214SStefano Zampini   }
6959566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals));
696a13144ffSStefano Zampini   if (print) {
6979566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs"));
6989566063dSJacob Faibussowitsch     PetscCall(ISView(primals,NULL));
699a13144ffSStefano Zampini   }
7009566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&bte));
701c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
7029566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc,primals));
7039566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&primals));
704a13144ffSStefano Zampini 
705a13144ffSStefano Zampini   /* Compute edge connectivity */
7069566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_"));
7074222ddf1SHong Zhang 
7084222ddf1SHong Zhang   /* Symbolic conn = lG*lGt */
7099566063dSJacob Faibussowitsch   PetscCall(MatProductCreate(lG,lGt,NULL,&conn));
7109566063dSJacob Faibussowitsch   PetscCall(MatProductSetType(conn,MATPRODUCT_AB));
7119566063dSJacob Faibussowitsch   PetscCall(MatProductSetAlgorithm(conn,"default"));
7129566063dSJacob Faibussowitsch   PetscCall(MatProductSetFill(conn,PETSC_DEFAULT));
7139566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)conn,"econn_"));
7149566063dSJacob Faibussowitsch   PetscCall(MatProductSetFromOptions(conn));
7159566063dSJacob Faibussowitsch   PetscCall(MatProductSymbolic(conn));
7164222ddf1SHong Zhang 
7179566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
718c2151214SStefano Zampini   if (fl2g) {
719c2151214SStefano Zampini     PetscBT   btf;
720c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
721c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
722c2151214SStefano Zampini 
723c2151214SStefano Zampini     /* create CSR for all local dofs */
7249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n+1,&iia));
725c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
72663a3b9bcSJacob 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);
727c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
728c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
729c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
730c2151214SStefano Zampini       rest = PETSC_TRUE;
7319566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done));
732c2151214SStefano Zampini     } else {
733c2151214SStefano Zampini       free   = PETSC_TRUE;
7349566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(n+1,&iiu,n,&jju));
735c2151214SStefano Zampini       iiu[0] = 0;
736c2151214SStefano Zampini       for (i=0;i<n;i++) {
737c2151214SStefano Zampini         iiu[i+1] = i+1;
738c2151214SStefano Zampini         jju[i]   = -1;
739d904f53bSStefano Zampini       }
740c2151214SStefano Zampini     }
741c2151214SStefano Zampini 
742c2151214SStefano Zampini     /* import sizes of CSR */
743c2151214SStefano Zampini     iia[0] = 0;
744c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
745c2151214SStefano Zampini 
746c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
7479566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(n,&btf));
7489566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(nedfieldlocal,&idxs));
749c2151214SStefano Zampini     for (i=0;i<ne;i++) {
7509566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(btf,idxs[i]));
751c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
752c2151214SStefano Zampini     }
753c2151214SStefano Zampini 
754c2151214SStefano Zampini     /* iia in CSR */
755c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
756c2151214SStefano Zampini 
757c2151214SStefano Zampini     /* jja in CSR */
7589566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(iia[n],&jja));
759c2151214SStefano Zampini     for (i=0;i<n;i++)
760c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
761c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
762c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
763c2151214SStefano Zampini 
764c2151214SStefano Zampini     /* map edge dofs connectivity */
7651e0482f5SStefano Zampini     if (jj) {
7669566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj));
767c2151214SStefano Zampini       for (i=0;i<ne;i++) {
768c2151214SStefano Zampini         PetscInt e = idxs[i];
769c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
770c2151214SStefano Zampini       }
7711e0482f5SStefano Zampini     }
7729566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(nedfieldlocal,&idxs));
7739566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER));
774c2151214SStefano Zampini     if (rest) {
7759566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done));
776c2151214SStefano Zampini     }
777c2151214SStefano Zampini     if (free) {
7789566063dSJacob Faibussowitsch       PetscCall(PetscFree2(iiu,jju));
779c2151214SStefano Zampini     }
7809566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&btf));
781c2151214SStefano Zampini   } else {
7829566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER));
783c2151214SStefano Zampini   }
784c2151214SStefano Zampini 
785a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
7869566063dSJacob Faibussowitsch   PetscCall(PCBDDCAnalyzeInterface(pc));
787213b8bfaSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
788a13144ffSStefano Zampini 
789a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
7909566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals));
7919566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
792a13144ffSStefano Zampini 
793c2151214SStefano Zampini   if (fl2g) {
7949566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals));
7959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nee,&eedges));
796c2151214SStefano Zampini     for (i=0;i<nee;i++) {
7979566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]));
798c2151214SStefano Zampini     }
799c2151214SStefano Zampini   } else {
800c2151214SStefano Zampini     eedges  = alleedges;
801c2151214SStefano Zampini     primals = allprimals;
802c2151214SStefano Zampini   }
803c2151214SStefano Zampini 
804a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
8059566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(marks,ne));
8069566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(primals,&cum));
8079566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(primals,&idxs));
808c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
8099566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(primals,&idxs));
810c2151214SStefano Zampini   if (print) {
8119566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs"));
8129566063dSJacob Faibussowitsch     PetscCall(ISView(primals,NULL));
813c2151214SStefano Zampini   }
814c2151214SStefano Zampini 
815c2151214SStefano Zampini   maxsize = 0;
816a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
817a13144ffSStefano Zampini     PetscInt size,mark = i+1;
818a13144ffSStefano Zampini 
8199566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(eedges[i],&size));
8209566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(eedges[i],&idxs));
821a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
8229566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(eedges[i],&idxs));
823a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
824a13144ffSStefano Zampini   }
825a13144ffSStefano Zampini 
826a13144ffSStefano Zampini   /* Find coarse edge endpoints */
8279566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
8289566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
829a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
830a13144ffSStefano Zampini     PetscInt mark = i+1,size;
831a13144ffSStefano Zampini 
8329566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(eedges[i],&size));
8331e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
83463a3b9bcSJacob Faibussowitsch     PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %" PetscInt_FMT,i);
8359566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(eedges[i],&idxs));
836a13144ffSStefano Zampini     if (print) {
83763a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %" PetscInt_FMT "\n",i));
8389566063dSJacob Faibussowitsch       PetscCall(ISView(eedges[i],NULL));
839a13144ffSStefano Zampini     }
840a13144ffSStefano Zampini     for (j=0;j<size;j++) {
841a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
84263a3b9bcSJacob Faibussowitsch       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %" PetscInt_FMT "\n",ee);
843a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
84463a3b9bcSJacob Faibussowitsch         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %" PetscInt_FMT "\n",jj[k]);
845a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
84663a3b9bcSJacob Faibussowitsch           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %" PetscInt_FMT "\n",jj[k]);
847a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
848a13144ffSStefano Zampini           PetscInt  k2;
849a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
850a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
85163a3b9bcSJacob 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]));
852c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
853c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
854c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
855a13144ffSStefano Zampini               corner = PETSC_TRUE;
856a13144ffSStefano Zampini               break;
857a13144ffSStefano Zampini             }
858a13144ffSStefano Zampini           }
859a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
86063a3b9bcSJacob Faibussowitsch             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %" PetscInt_FMT "\n",jj[k]);
8619566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(btv,jj[k]));
862a13144ffSStefano Zampini           } else {
863a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
864a13144ffSStefano Zampini           }
865a13144ffSStefano Zampini         }
866a13144ffSStefano Zampini       }
867a13144ffSStefano Zampini     }
8689566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(eedges[i],&idxs));
869a13144ffSStefano Zampini   }
8709566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
8719566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
8729566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btb));
873a13144ffSStefano Zampini 
874a13144ffSStefano Zampini   /* Reset marked primal dofs */
8759566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(primals,&cum));
8769566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(primals,&idxs));
877a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
8789566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(primals,&idxs));
879a13144ffSStefano Zampini 
8800569b399SStefano Zampini   /* Now use the initial lG */
8819566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lG));
8829566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lGt));
8830569b399SStefano Zampini   lG   = lGinit;
8849566063dSJacob Faibussowitsch   PetscCall(MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt));
8850569b399SStefano Zampini 
886a13144ffSStefano Zampini   /* Compute extended cols indices */
8879566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nv,&btvc));
8889566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nee,&bter));
8899566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
8909566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetMaxRowNonzeros(lG,&i));
891a13144ffSStefano Zampini   i   *= maxsize;
8929566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nee,&extcols));
8939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(i,&extrow,i,&gidxs));
894a13144ffSStefano Zampini   eerr = PETSC_FALSE;
895a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
896b03ebc13SStefano Zampini     PetscInt size,found = 0;
897a13144ffSStefano Zampini 
898a13144ffSStefano Zampini     cum  = 0;
8999566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(eedges[i],&size));
9001e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
90163a3b9bcSJacob Faibussowitsch     PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %" PetscInt_FMT,i);
9029566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(eedges[i],&idxs));
9039566063dSJacob Faibussowitsch     PetscCall(PetscBTMemzero(nv,btvc));
904a13144ffSStefano Zampini     for (j=0;j<size;j++) {
905a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
906b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
907b03ebc13SStefano Zampini         PetscInt vv = jj[k];
908b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
909b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
910b03ebc13SStefano Zampini       }
911a13144ffSStefano Zampini     }
9129566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(eedges[i],&idxs));
9139566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsInt(&cum,extrow));
9149566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs));
9159566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(cum,gidxs,extrow));
9169566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]));
917a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
918a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
919b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
9209566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(bter,i));
921a13144ffSStefano Zampini       if (print) {
9229566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)eedges[i],"error_edge"));
9239566063dSJacob Faibussowitsch         PetscCall(ISView(eedges[i],NULL));
9249566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)extcols[i],"error_extcol"));
9259566063dSJacob Faibussowitsch         PetscCall(ISView(extcols[i],NULL));
926a13144ffSStefano Zampini       }
927a13144ffSStefano Zampini       eerr = PETSC_TRUE;
928a13144ffSStefano Zampini     }
929a13144ffSStefano Zampini   }
93028b400f6SJacob Faibussowitsch   /* PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
9311c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm));
932a13144ffSStefano Zampini   if (done) {
933a13144ffSStefano Zampini     PetscInt *newprimals;
934a13144ffSStefano Zampini 
9359566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ne,&newprimals));
9369566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(primals,&cum));
9379566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(primals,&idxs));
9389566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(newprimals,idxs,cum));
9399566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(primals,&idxs));
9409566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
94163a3b9bcSJacob Faibussowitsch     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %s)\n",PetscBools[eerr]);
942a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
943b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
944b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
945a13144ffSStefano Zampini         PetscInt size,mark = i+1;
946a13144ffSStefano Zampini 
9479566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(eedges[i],&size));
9489566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(eedges[i],&idxs));
949c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
950a13144ffSStefano Zampini         for (j=0;j<size;j++) {
951a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
95263a3b9bcSJacob Faibussowitsch           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %" PetscInt_FMT " [%" PetscInt_FMT " %" PetscInt_FMT ")\n",ee,ii[ee],ii[ee+1]);
953a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
954a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
955a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
956a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
957b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
95863a3b9bcSJacob Faibussowitsch               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %" PetscInt_FMT "\n",vv);
9599566063dSJacob Faibussowitsch               PetscCall(PetscBTSet(btv,vv));
960a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
961a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
962a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
963a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
96463a3b9bcSJacob Faibussowitsch                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %" PetscInt_FMT "\n",ee2);
965a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
966a13144ffSStefano Zampini                   /* finally set the new corners */
967a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
96863a3b9bcSJacob Faibussowitsch                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %" PetscInt_FMT "\n",jj[k3]);
9699566063dSJacob Faibussowitsch                     PetscCall(PetscBTSet(btv,jj[k3]));
970a13144ffSStefano Zampini                   }
971a13144ffSStefano Zampini                 }
972a13144ffSStefano Zampini               }
973b03ebc13SStefano Zampini             } else {
97463a3b9bcSJacob Faibussowitsch               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %" PetscInt_FMT "\n",jj[k]);
975a13144ffSStefano Zampini             }
976a13144ffSStefano Zampini           }
977a13144ffSStefano Zampini         }
978b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
979b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
980b03ebc13SStefano Zampini 
9819566063dSJacob Faibussowitsch           PetscCall(PetscCalloc1(ne,&tmarks));
98263a3b9bcSJacob Faibussowitsch           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %" PetscInt_FMT "\n",i);
983b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
984b03ebc13SStefano Zampini             PetscInt k2;
98563a3b9bcSJacob Faibussowitsch             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %" PetscInt_FMT "\n",jj[k]);
9869566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(btv,jj[k]));
987b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
988b03ebc13SStefano Zampini           }
989b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
990b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
99163a3b9bcSJacob Faibussowitsch               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %" PetscInt_FMT "\n",idxs[j]);
992b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
993b03ebc13SStefano Zampini             }
994b03ebc13SStefano Zampini           }
9959566063dSJacob Faibussowitsch           PetscCall(PetscFree(tmarks));
996b03ebc13SStefano Zampini         }
9979566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(eedges[i],&idxs));
998a13144ffSStefano Zampini       }
9999566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&extcols[i]));
1000a13144ffSStefano Zampini     }
10019566063dSJacob Faibussowitsch     PetscCall(PetscFree(extcols));
10029566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done));
10039566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsInt(&cum,newprimals));
1004c2151214SStefano Zampini     if (fl2g) {
10059566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals));
10069566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&primals));
1007c2151214SStefano Zampini       for (i=0;i<nee;i++) {
10089566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&eedges[i]));
1009c2151214SStefano Zampini       }
10109566063dSJacob Faibussowitsch       PetscCall(PetscFree(eedges));
1011c2151214SStefano Zampini     }
10129566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals));
10139566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals));
10149566063dSJacob Faibussowitsch     PetscCall(PetscFree(newprimals));
10159566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc,primals));
10169566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&primals));
10179566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
1018213b8bfaSStefano Zampini     pcbddc->mat_graph->twodim = PETSC_FALSE;
10199566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals));
1020c2151214SStefano Zampini     if (fl2g) {
10219566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals));
10229566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nee,&eedges));
1023c2151214SStefano Zampini       for (i=0;i<nee;i++) {
10249566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]));
1025c2151214SStefano Zampini       }
1026c2151214SStefano Zampini     } else {
1027c2151214SStefano Zampini       eedges  = alleedges;
1028c2151214SStefano Zampini       primals = allprimals;
1029c2151214SStefano Zampini     }
10309566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nee,&extcols));
1031a13144ffSStefano Zampini 
1032a13144ffSStefano Zampini     /* Mark again */
10339566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(marks,ne));
1034a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1035a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1036a13144ffSStefano Zampini 
10379566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(eedges[i],&size));
10389566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(eedges[i],&idxs));
1039a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
10409566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(eedges[i],&idxs));
1041a13144ffSStefano Zampini     }
1042a13144ffSStefano Zampini     if (print) {
10439566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass"));
10449566063dSJacob Faibussowitsch       PetscCall(ISView(primals,NULL));
1045a13144ffSStefano Zampini     }
1046a13144ffSStefano Zampini 
1047a13144ffSStefano Zampini     /* Recompute extended cols */
1048a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1049a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1050a13144ffSStefano Zampini       PetscInt size;
1051a13144ffSStefano Zampini 
1052a13144ffSStefano Zampini       cum  = 0;
10539566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(eedges[i],&size));
10541e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
105563a3b9bcSJacob Faibussowitsch       PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %" PetscInt_FMT,i);
10569566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(eedges[i],&idxs));
1057a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1058a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10591e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1060a13144ffSStefano Zampini       }
10619566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(eedges[i],&idxs));
10629566063dSJacob Faibussowitsch       PetscCall(PetscSortRemoveDupsInt(&cum,extrow));
10639566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs));
10649566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithArray(cum,gidxs,extrow));
10659566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]));
1066a13144ffSStefano Zampini       if (cum != size -1) {
1067a13144ffSStefano Zampini         if (print) {
10689566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass"));
10699566063dSJacob Faibussowitsch           PetscCall(ISView(eedges[i],NULL));
10709566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass"));
10719566063dSJacob Faibussowitsch           PetscCall(ISView(extcols[i],NULL));
1072a13144ffSStefano Zampini         }
1073a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1074a13144ffSStefano Zampini       }
1075a13144ffSStefano Zampini     }
1076a13144ffSStefano Zampini   }
10779566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
10789566063dSJacob Faibussowitsch   PetscCall(PetscFree2(extrow,gidxs));
10799566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&bter));
10809566063dSJacob Faibussowitsch   if (print) PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF));
1081a13144ffSStefano Zampini   /* an error should not occur at this point */
108228b400f6SJacob Faibussowitsch   PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1083a13144ffSStefano Zampini 
10844e64d54eSstefano_zampini   /* Check the number of endpoints */
10859566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
10869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2*nee,&corners));
10879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nee,&cedges));
10884e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1089b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
10904e64d54eSstefano_zampini 
1091b03ebc13SStefano Zampini     /* init with defaults */
1092b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
10939566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(eedges[i],&size));
10941e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
109563a3b9bcSJacob Faibussowitsch     PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %" PetscInt_FMT,i);
10969566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(eedges[i],&idxs));
10979566063dSJacob Faibussowitsch     PetscCall(PetscBTMemzero(nv,btvc));
10984e64d54eSstefano_zampini     for (j=0;j<size;j++) {
10994e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
11004e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
11014e64d54eSstefano_zampini         PetscInt vv = jj[k];
11024e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
110363a3b9bcSJacob Faibussowitsch           PetscCheck(found != 2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %" PetscInt_FMT,i);
1104b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11054e64d54eSstefano_zampini         }
11064e64d54eSstefano_zampini       }
11074e64d54eSstefano_zampini     }
1108b03ebc13SStefano Zampini     if (found != 2) {
1109b03ebc13SStefano Zampini       PetscInt e;
1110b03ebc13SStefano Zampini       if (fl2g) {
11119566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingApply(fl2g,1,idxs,&e));
1112b03ebc13SStefano Zampini       } else {
1113b03ebc13SStefano Zampini         e = idxs[0];
1114b03ebc13SStefano Zampini       }
111563a3b9bcSJacob 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]);
1116b03ebc13SStefano Zampini     }
1117eee23b56SStefano Zampini 
1118eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
11199566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc));
1120b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1121b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1122b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1123b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1124b03ebc13SStefano Zampini     }
1125eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11269566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(eedges[i],&idxs));
112763a3b9bcSJacob 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]);
11284e64d54eSstefano_zampini   }
11299566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
11309566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btvc));
11314e64d54eSstefano_zampini 
113276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1133a13144ffSStefano Zampini     /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1134a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
11359566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nee+1,&emarks));
11369566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
1137a13144ffSStefano Zampini     for (i=0;i<nv;i++) {
1138a13144ffSStefano Zampini       PetscInt emax = 0,eemax = 0;
1139a13144ffSStefano Zampini 
1140a13144ffSStefano Zampini       if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
11419566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(emarks,nee+1));
1142a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1143a13144ffSStefano Zampini       for (j=1;j<nee+1;j++) {
1144a13144ffSStefano Zampini         if (emax < emarks[j]) {
1145a13144ffSStefano Zampini           emax = emarks[j];
1146a13144ffSStefano Zampini           eemax = j;
1147a13144ffSStefano Zampini         }
1148a13144ffSStefano Zampini       }
1149a13144ffSStefano Zampini       /* not relevant for edges */
1150a13144ffSStefano Zampini       if (!eemax) continue;
1151a13144ffSStefano Zampini 
1152a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
1153a13144ffSStefano Zampini         if (marks[jj[j]] && marks[jj[j]] != eemax) {
115463a3b9bcSJacob 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]);
1155a13144ffSStefano Zampini         }
1156a13144ffSStefano Zampini       }
1157a13144ffSStefano Zampini     }
11589566063dSJacob Faibussowitsch     PetscCall(PetscFree(emarks));
11599566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
116076bd3646SJed Brown   }
1161a13144ffSStefano Zampini 
1162a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
11639566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
11649566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetMaxRowNonzeros(lGt,&extmem));
1165a13144ffSStefano Zampini   extmem *= maxsize;
11669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(extmem*nee,&extrow));
11679566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nee,&extrows));
11689566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nee,&extrowcum));
1169a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1170a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1171213b8bfaSStefano Zampini 
1172a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1173a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1174a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1175a13144ffSStefano Zampini         mark = marks[jj[j]];
1176a13144ffSStefano Zampini 
1177a13144ffSStefano Zampini     /* not relevant */
1178a13144ffSStefano Zampini     if (!mark) continue;
1179a13144ffSStefano Zampini 
1180a13144ffSStefano Zampini     /* import extended row */
1181a13144ffSStefano Zampini     mark--;
1182a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1183a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
118463a3b9bcSJacob Faibussowitsch     PetscCheck(extrowcum[mark] + size <= extmem,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %" PetscInt_FMT " > %" PetscInt_FMT,extrowcum[mark] + size,extmem);
11859566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(extrow+start,jj+ii[i],size));
1186a13144ffSStefano Zampini     extrowcum[mark] += size;
1187a13144ffSStefano Zampini   }
11889566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done));
11899566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lGt));
11909566063dSJacob Faibussowitsch   PetscCall(PetscFree(marks));
1191213b8bfaSStefano Zampini 
1192213b8bfaSStefano Zampini   /* Compress extrows */
1193a13144ffSStefano Zampini   cum  = 0;
1194a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1195a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
11969566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsInt(&size,start));
11979566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]));
1198a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1199a13144ffSStefano Zampini   }
12009566063dSJacob Faibussowitsch   PetscCall(PetscFree(extrowcum));
12019566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btv));
12029566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&btvcand));
1203a13144ffSStefano Zampini 
1204a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
12059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork));
1206a13144ffSStefano Zampini 
1207a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
12089566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,&T));
1209d0609cedSBarry Smith   PetscCall(MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,pc->pmat->rmap->N,pc->pmat->rmap->N));
12109566063dSJacob Faibussowitsch   PetscCall(MatSetType(T,MATAIJ));
12119566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(T,10,NULL));
12129566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(T,10,NULL,10,NULL));
12139566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(T,al2g,al2g));
12149566063dSJacob Faibussowitsch   PetscCall(MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE));
12159566063dSJacob Faibussowitsch   PetscCall(MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE));
12169566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&al2g));
1217a13144ffSStefano Zampini 
1218a13144ffSStefano Zampini   /* Defaults to identity */
12199566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat,&tvec,NULL));
12209566063dSJacob Faibussowitsch   PetscCall(VecSet(tvec,1.0));
12219566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet(T,tvec,INSERT_VALUES));
12229566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tvec));
1223a13144ffSStefano Zampini 
12241e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->nedcG));
12269566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->nedclocal));
12271e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12281e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12291e0482f5SStefano Zampini     IS                     wis,gwis;
12301e0482f5SStefano Zampini     PetscInt               cnv,cne;
12311e0482f5SStefano Zampini 
12329566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis));
12331e0482f5SStefano Zampini     if (fl2g) {
12349566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal));
12351e0482f5SStefano Zampini     } else {
12369566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)wis));
12371e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12381e0482f5SStefano Zampini     }
12399566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis));
12409566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&wis));
12419566063dSJacob Faibussowitsch     PetscCall(ISRenumber(gwis,NULL,&cne,&wis));
12429566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(wis,&cel2g));
12439566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&wis));
12449566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gwis));
12451e0482f5SStefano Zampini 
12469566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis));
12479566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis));
12489566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&wis));
12499566063dSJacob Faibussowitsch     PetscCall(ISRenumber(gwis,NULL,&cnv,&wis));
12509566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(wis,&cvl2g));
12519566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&wis));
12529566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gwis));
12531e0482f5SStefano Zampini 
12549566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,&pcbddc->nedcG));
12559566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv));
12569566063dSJacob Faibussowitsch     PetscCall(MatSetType(pcbddc->nedcG,MATAIJ));
12579566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL));
12589566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL));
12599566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g));
12609566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cel2g));
12619566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cvl2g));
12621e0482f5SStefano Zampini   }
12639566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&vl2g));
12641e0482f5SStefano Zampini 
12651e0482f5SStefano Zampini #if defined(PRINT_GDET)
12661e0482f5SStefano Zampini   inc = 0;
12671e0482f5SStefano Zampini   lev = pcbddc->current_level;
12681e0482f5SStefano Zampini #endif
1269213b8bfaSStefano Zampini 
1270213b8bfaSStefano Zampini   /* Insert values in the change of basis matrix */
1271a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1272a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12731e0482f5SStefano Zampini     IS          cornersis = NULL;
12741e0482f5SStefano Zampini     PetscScalar cvals[2];
1275a13144ffSStefano Zampini 
12761e0482f5SStefano Zampini     if (pcbddc->nedcG) {
12779566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis));
12781e0482f5SStefano Zampini     }
12799566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork));
1280a13144ffSStefano Zampini     if (Gins && GKins) {
12811683a169SBarry Smith       const PetscScalar *data;
1282a13144ffSStefano Zampini       const PetscInt    *rows,*cols;
1283a13144ffSStefano Zampini       PetscInt          nrh,nch,nrc,ncc;
1284a13144ffSStefano Zampini 
12859566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(eedges[i],&cols));
1286a13144ffSStefano Zampini       /* H1 */
12879566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(extrows[i],&rows));
12889566063dSJacob Faibussowitsch       PetscCall(MatGetSize(Gins,&nrh,&nch));
12899566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(Gins,&data));
12909566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES));
12919566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(Gins,&data));
12929566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(extrows[i],&rows));
1293a13144ffSStefano Zampini       /* complement */
12949566063dSJacob Faibussowitsch       PetscCall(MatGetSize(GKins,&nrc,&ncc));
129563a3b9bcSJacob Faibussowitsch       PetscCheck(ncc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %" PetscInt_FMT,i);
129663a3b9bcSJacob 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);
129763a3b9bcSJacob 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);
12989566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(GKins,&data));
12999566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES));
13009566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(GKins,&data));
13011e0482f5SStefano Zampini 
13021e0482f5SStefano Zampini       /* coarse discrete gradient */
13031e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13041e0482f5SStefano Zampini         PetscInt cols[2];
13051e0482f5SStefano Zampini 
13061e0482f5SStefano Zampini         cols[0] = 2*i;
13071e0482f5SStefano Zampini         cols[1] = 2*i+1;
13089566063dSJacob Faibussowitsch         PetscCall(MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES));
13091e0482f5SStefano Zampini       }
13109566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(eedges[i],&cols));
1311a13144ffSStefano Zampini     }
13129566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&extrows[i]));
13139566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&extcols[i]));
13149566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cornersis));
13159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Gins));
13169566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&GKins));
1317a13144ffSStefano Zampini   }
13189566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&el2g));
1319a13144ffSStefano Zampini 
1320a13144ffSStefano Zampini   /* Start assembling */
13219566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY));
13221e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13239566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY));
13241e0482f5SStefano Zampini   }
1325a13144ffSStefano Zampini 
1326a13144ffSStefano Zampini   /* Free */
1327c2151214SStefano Zampini   if (fl2g) {
13289566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&primals));
1329c2151214SStefano Zampini     for (i=0;i<nee;i++) {
13309566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&eedges[i]));
1331c2151214SStefano Zampini     }
13329566063dSJacob Faibussowitsch     PetscCall(PetscFree(eedges));
1333c2151214SStefano Zampini   }
1334eee23b56SStefano Zampini 
1335eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1336eee23b56SStefano Zampini   {
1337eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1338eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1339eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1340eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1341eee23b56SStefano Zampini 
1342eee23b56SStefano Zampini     /* find first primal edge */
1343eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
13449566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs));
1345eee23b56SStefano Zampini     } else {
1346eee23b56SStefano Zampini       if (fl2g) {
13479566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges));
1348eee23b56SStefano Zampini       }
1349eee23b56SStefano Zampini       idxs = cedges;
1350eee23b56SStefano Zampini     }
1351eee23b56SStefano Zampini     cum = 0;
1352eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1353eee23b56SStefano Zampini 
1354eee23b56SStefano Zampini     /* adapt connected components */
13559566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue));
1356eee23b56SStefano Zampini     graph->cptr[0] = 0;
1357eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1358eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1359eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1360eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1361eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1362eee23b56SStefano Zampini         ncc++;
1363eee23b56SStefano Zampini         lc--;
1364eee23b56SStefano Zampini         cum++;
1365eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1366eee23b56SStefano Zampini       }
1367eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1368eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1369eee23b56SStefano Zampini       ncc++;
1370eee23b56SStefano Zampini     }
1371eee23b56SStefano Zampini     graph->ncc = ncc;
1372eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
13739566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs));
1374eee23b56SStefano Zampini     }
13759566063dSJacob Faibussowitsch     PetscCall(PetscFree2(ocptr,oqueue));
1376eee23b56SStefano Zampini   }
13779566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&fl2g));
13789566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals));
13799566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphResetCSR(pcbddc->mat_graph));
13809566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&conn));
1381eee23b56SStefano Zampini 
13829566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&nedfieldlocal));
13839566063dSJacob Faibussowitsch   PetscCall(PetscFree(extrow));
13849566063dSJacob Faibussowitsch   PetscCall(PetscFree2(work,rwork));
13859566063dSJacob Faibussowitsch   PetscCall(PetscFree(corners));
13869566063dSJacob Faibussowitsch   PetscCall(PetscFree(cedges));
13879566063dSJacob Faibussowitsch   PetscCall(PetscFree(extrows));
13889566063dSJacob Faibussowitsch   PetscCall(PetscFree(extcols));
13899566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lG));
1390a13144ffSStefano Zampini 
1391a13144ffSStefano Zampini   /* Complete assembling */
13929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY));
13931e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13949566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY));
13951e0482f5SStefano Zampini #if 0
13969566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G"));
13979566063dSJacob Faibussowitsch     PetscCall(MatView(pcbddc->nedcG,NULL));
13981e0482f5SStefano Zampini #endif
13991e0482f5SStefano Zampini   }
1400a13144ffSStefano Zampini 
1401a13144ffSStefano Zampini   /* set change of basis */
14029566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetChangeOfBasisMat(pc,T,singular));
14039566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&T));
1404a13144ffSStefano Zampini 
1405a13144ffSStefano Zampini   PetscFunctionReturn(0);
1406a13144ffSStefano Zampini }
1407a13144ffSStefano Zampini 
1408d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1409d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1410d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1411d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1412d8203eabSStefano Zampini {
1413d8203eabSStefano Zampini   PetscInt       i;
1414d8203eabSStefano Zampini 
1415d8203eabSStefano Zampini   PetscFunctionBegin;
1416d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1417d8203eabSStefano Zampini     PetscInt first,last;
1418d8203eabSStefano Zampini 
14199566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(quad_vecs[i],&first,&last));
14207827d75bSBarry Smith     PetscCheck(last-first >= 2*nvecs || !has_const,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1421d8203eabSStefano Zampini     if (i>=first && i < last) {
1422d8203eabSStefano Zampini       PetscScalar *data;
14239566063dSJacob Faibussowitsch       PetscCall(VecGetArray(quad_vecs[i],&data));
1424d8203eabSStefano Zampini       if (!has_const) {
1425d8203eabSStefano Zampini         data[i-first] = 1.;
1426d8203eabSStefano Zampini       } else {
142786fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
142886fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1429d8203eabSStefano Zampini       }
14309566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(quad_vecs[i],&data));
1431d8203eabSStefano Zampini     }
14329566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i]));
1433d8203eabSStefano Zampini   }
14349566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp));
1435d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1436d8203eabSStefano Zampini     PetscInt first,last;
14379566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(quad_vecs[i]));
14389566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(quad_vecs[i],&first,&last));
1439d8203eabSStefano Zampini     if (i>=first && i < last) {
1440d8203eabSStefano Zampini       PetscScalar *data;
14419566063dSJacob Faibussowitsch       PetscCall(VecGetArray(quad_vecs[i],&data));
1442d8203eabSStefano Zampini       if (!has_const) {
1443d8203eabSStefano Zampini         data[i-first] = 0.;
1444d8203eabSStefano Zampini       } else {
144586fa73c5SStefano Zampini         data[2*i-first] = 0.;
144686fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1447d8203eabSStefano Zampini       }
14489566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(quad_vecs[i],&data));
1449d8203eabSStefano Zampini     }
14509566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i]));
14519566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(quad_vecs[i]));
1452d8203eabSStefano Zampini   }
1453d8203eabSStefano Zampini   PetscFunctionReturn(0);
1454d8203eabSStefano Zampini }
1455d8203eabSStefano Zampini 
14568ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1457669cc0f4SStefano Zampini {
1458a198735bSStefano Zampini   Mat                    loc_divudotp;
1459fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14608ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1461669cc0f4SStefano Zampini   PetscScalar            *vals;
1462669cc0f4SStefano Zampini   const PetscScalar      *array;
14630f04eeffSStefano Zampini   PetscInt               i,maxneighs = 0,maxsize,*gidxs;
1464a040e873SStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
14651ae86dd6SStefano Zampini   PetscMPIInt            rank;
1466669cc0f4SStefano Zampini 
1467669cc0f4SStefano Zampini   PetscFunctionBegin;
14689566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared));
14690f04eeffSStefano Zampini   for (i=0;i<n_neigh;i++) maxneighs = PetscMax(graph->count[shared[i][0]]+1,maxneighs);
14701c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(MPI_IN_PLACE,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A)));
14718037d520SStefano Zampini   if (!maxneighs) {
14729566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared));
14738037d520SStefano Zampini     *nnsp = NULL;
14748037d520SStefano Zampini     PetscFunctionReturn(0);
1475669cc0f4SStefano Zampini   }
1476669cc0f4SStefano Zampini   maxsize = 0;
1477a040e873SStefano Zampini   for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize);
14789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(maxsize,&gidxs,maxsize,&vals));
1479669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
14809566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A,&quad_vec,NULL));
14818ae0ca82SStefano Zampini   if (!transpose) {
14829566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(A,&map,NULL));
14838ae0ca82SStefano Zampini   } else {
14849566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(A,NULL,&map));
14858ae0ca82SStefano Zampini   }
14869566063dSJacob Faibussowitsch   PetscCall(VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs));
14879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&quad_vec));
14889566063dSJacob Faibussowitsch   PetscCall(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp));
1489669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
14909566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(quad_vecs[i]));
1491669cc0f4SStefano Zampini   }
1492d8203eabSStefano Zampini 
1493669cc0f4SStefano Zampini   /* compute local quad vec */
14949566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(divudotp,&loc_divudotp));
14958ae0ca82SStefano Zampini   if (!transpose) {
14969566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(loc_divudotp,&v,&p));
14978ae0ca82SStefano Zampini   } else {
14989566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(loc_divudotp,&p,&v));
14998ae0ca82SStefano Zampini   }
15009566063dSJacob Faibussowitsch   PetscCall(VecSet(p,1.));
15018ae0ca82SStefano Zampini   if (!transpose) {
15029566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(loc_divudotp,p,v));
15038ae0ca82SStefano Zampini   } else {
15049566063dSJacob Faibussowitsch     PetscCall(MatMult(loc_divudotp,p,v));
15058ae0ca82SStefano Zampini   }
1506fa23a32eSStefano Zampini   if (vl2l) {
1507187c917aSStefano Zampini     Mat        lA;
1508187c917aSStefano Zampini     VecScatter sc;
1509187c917aSStefano Zampini 
15109566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(A,&lA));
15119566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(lA,&vins,NULL));
15129566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(v,NULL,vins,vl2l,&sc));
15139566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD));
15149566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD));
15159566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sc));
1516fa23a32eSStefano Zampini   } else {
1517fa23a32eSStefano Zampini     vins = v;
1518fa23a32eSStefano Zampini   }
15199566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(vins,&array));
15209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&p));
15219a962809SStefano Zampini 
15221ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank));
15240f04eeffSStefano Zampini   for (i=1;i<n_neigh;i++) {
1525669cc0f4SStefano Zampini     const PetscInt    *idxs;
1526669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1527669cc0f4SStefano Zampini 
1528a040e873SStefano Zampini     idxs = shared[i];
1529a040e873SStefano Zampini     nn   = n_shared[i];
1530669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15319566063dSJacob Faibussowitsch     PetscCall(PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx));
1532669cc0f4SStefano Zampini     idx  = -(idx+1);
153363a3b9bcSJacob Faibussowitsch     PetscCheck(idx >= 0 && idx < maxneighs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid index %" PetscInt_FMT " not in [0,%" PetscInt_FMT ")",idx,maxneighs);
15349566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(map,nn,idxs,gidxs));
15359566063dSJacob Faibussowitsch     PetscCall(VecSetValues(quad_vecs[idx],nn,gidxs,vals,INSERT_VALUES));
1536669cc0f4SStefano Zampini   }
15379566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared));
15389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(vins,&array));
1539fa23a32eSStefano Zampini   if (vl2l) {
15409566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vins));
1541fa23a32eSStefano Zampini   }
15429566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v));
15439566063dSJacob Faibussowitsch   PetscCall(PetscFree2(gidxs,vals));
1544669cc0f4SStefano Zampini 
1545669cc0f4SStefano Zampini   /* assemble near null space */
1546669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
15479566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(quad_vecs[i]));
1548669cc0f4SStefano Zampini   }
1549669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
15509566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(quad_vecs[i]));
15519566063dSJacob Faibussowitsch     PetscCall(VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view"));
15529566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(quad_vecs[i]));
1553669cc0f4SStefano Zampini   }
15549566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(maxneighs,&quad_vecs));
1555669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1556669cc0f4SStefano Zampini }
1557669cc0f4SStefano Zampini 
15587620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv)
15597620a527SStefano Zampini {
15607620a527SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15617620a527SStefano Zampini 
15627620a527SStefano Zampini   PetscFunctionBegin;
15637620a527SStefano Zampini   if (primalv) {
15647620a527SStefano Zampini     if (pcbddc->user_primal_vertices_local) {
15657620a527SStefano Zampini       IS list[2], newp;
15667620a527SStefano Zampini 
15677620a527SStefano Zampini       list[0] = primalv;
15687620a527SStefano Zampini       list[1] = pcbddc->user_primal_vertices_local;
15699566063dSJacob Faibussowitsch       PetscCall(ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp));
15709566063dSJacob Faibussowitsch       PetscCall(ISSortRemoveDups(newp));
15719566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&list[1]));
15727620a527SStefano Zampini       pcbddc->user_primal_vertices_local = newp;
15737620a527SStefano Zampini     } else {
15749566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc,primalv));
15757620a527SStefano Zampini     }
15767620a527SStefano Zampini   }
15777620a527SStefano Zampini   PetscFunctionReturn(0);
15787620a527SStefano Zampini }
1579669cc0f4SStefano Zampini 
15801c7a958bSStefano Zampini static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx)
15811c7a958bSStefano Zampini {
15821c7a958bSStefano Zampini   PetscInt f, *comp  = (PetscInt *)ctx;
15831c7a958bSStefano Zampini 
15841c7a958bSStefano Zampini   PetscFunctionBegin;
15851c7a958bSStefano Zampini   for (f=0;f<Nf;f++) out[f] = X[*comp];
15861c7a958bSStefano Zampini   PetscFunctionReturn(0);
15871c7a958bSStefano Zampini }
1588674ae819SStefano Zampini 
15891f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
15901f4df5f7SStefano Zampini {
15911f4df5f7SStefano Zampini   Vec            local,global;
15921f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15931f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
15945c5e10d6SStefano Zampini   PetscBool      monolithic = PETSC_FALSE;
15951f4df5f7SStefano Zampini 
15961f4df5f7SStefano Zampini   PetscFunctionBegin;
1597d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");
15989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL));
1599d0609cedSBarry Smith   PetscOptionsEnd();
16001f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
16019566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat,&global,NULL));
16029566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(matis->A,&local,NULL));
16039566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(global,PETSC_TRUE));
16049566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(local,PETSC_TRUE));
16056a8fc67bSStefano Zampini   if (monolithic) { /* just get block size to properly compute vertices */
16066a8fc67bSStefano Zampini     if (pcbddc->vertex_size == 1) {
16079566063dSJacob Faibussowitsch       PetscCall(MatGetBlockSize(pc->pmat,&pcbddc->vertex_size));
16086a8fc67bSStefano Zampini     }
16096a8fc67bSStefano Zampini     goto boundary;
16106a8fc67bSStefano Zampini   }
16115c5e10d6SStefano Zampini 
16121f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16131f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16141f4df5f7SStefano Zampini       PetscInt i;
16150c85b387SStefano Zampini 
16169566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal));
16171f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16180c85b387SStefano Zampini         PetscInt bs;
16190c85b387SStefano Zampini 
16209566063dSJacob Faibussowitsch         PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]));
16219566063dSJacob Faibussowitsch         PetscCall(ISGetBlockSize(pcbddc->ISForDofs[i],&bs));
16229566063dSJacob Faibussowitsch         PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs));
16239566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
16241f4df5f7SStefano Zampini       }
16251f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16261f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16279566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddc->ISForDofs));
16281f4df5f7SStefano Zampini     }
16291f4df5f7SStefano Zampini   } else {
163021ef3d20SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present */
163121ef3d20SStefano Zampini       DM dm;
163221ef3d20SStefano Zampini 
16339566063dSJacob Faibussowitsch       PetscCall(MatGetDM(pc->pmat, &dm));
16344f819b78SStefano Zampini       if (!dm) {
16359566063dSJacob Faibussowitsch         PetscCall(PCGetDM(pc, &dm));
163621ef3d20SStefano Zampini       }
163721ef3d20SStefano Zampini       if (dm) {
163821ef3d20SStefano Zampini         IS      *fields;
163921ef3d20SStefano Zampini         PetscInt nf,i;
16400c85b387SStefano Zampini 
16419566063dSJacob Faibussowitsch         PetscCall(DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL));
16429566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nf,&pcbddc->ISForDofsLocal));
164321ef3d20SStefano Zampini         for (i=0;i<nf;i++) {
16440c85b387SStefano Zampini           PetscInt bs;
16450c85b387SStefano Zampini 
16469566063dSJacob Faibussowitsch           PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i]));
16479566063dSJacob Faibussowitsch           PetscCall(ISGetBlockSize(fields[i],&bs));
16489566063dSJacob Faibussowitsch           PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs));
16499566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&fields[i]));
165021ef3d20SStefano Zampini         }
16519566063dSJacob Faibussowitsch         PetscCall(PetscFree(fields));
165221ef3d20SStefano Zampini         pcbddc->n_ISForDofsLocal = nf;
165321ef3d20SStefano Zampini       } else { /* See if MATIS has fields attached by the conversion from MatNest */
165421ef3d20SStefano Zampini         PetscContainer   c;
165521ef3d20SStefano Zampini 
16569566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c));
165721ef3d20SStefano Zampini         if (c) {
165821ef3d20SStefano Zampini           MatISLocalFields lf;
16599566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c,(void**)&lf));
16609566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf));
166121ef3d20SStefano Zampini         } else { /* fallback, create the default fields if bs > 1 */
16621f4df5f7SStefano Zampini           PetscInt i, n = matis->A->rmap->n;
16639566063dSJacob Faibussowitsch           PetscCall(MatGetBlockSize(pc->pmat,&i));
166421ef3d20SStefano Zampini           if (i > 1) {
1665986cdee1SStefano Zampini             pcbddc->n_ISForDofsLocal = i;
16669566063dSJacob Faibussowitsch             PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal));
16671f4df5f7SStefano Zampini             for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16689566063dSJacob Faibussowitsch               PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]));
16691f4df5f7SStefano Zampini             }
16701f4df5f7SStefano Zampini           }
167121ef3d20SStefano Zampini         }
167221ef3d20SStefano Zampini       }
16737a0e7b2cSstefano_zampini     } else {
16747a0e7b2cSstefano_zampini       PetscInt i;
16757a0e7b2cSstefano_zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16769566063dSJacob Faibussowitsch         PetscCall(PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i]));
16777a0e7b2cSstefano_zampini       }
16781f4df5f7SStefano Zampini     }
1679986cdee1SStefano Zampini   }
16801f4df5f7SStefano Zampini 
16815c5e10d6SStefano Zampini boundary:
16821f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16839566063dSJacob Faibussowitsch     PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal));
16847a0e7b2cSstefano_zampini   } else if (pcbddc->DirichletBoundariesLocal) {
16859566063dSJacob Faibussowitsch     PetscCall(PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal));
16861f4df5f7SStefano Zampini   }
16871f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16889566063dSJacob Faibussowitsch     PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal));
16897a0e7b2cSstefano_zampini   } else if (pcbddc->NeumannBoundariesLocal) {
16909566063dSJacob Faibussowitsch     PetscCall(PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal));
16911f4df5f7SStefano Zampini   }
16921f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16939566063dSJacob Faibussowitsch     PetscCall(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local));
16941f4df5f7SStefano Zampini   }
16959566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&global));
16969566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&local));
16977620a527SStefano Zampini   /* detect local disconnected subdomains if requested (use matis->A) */
16987620a527SStefano Zampini   if (pcbddc->detect_disconnected) {
16997620a527SStefano Zampini     IS        primalv = NULL;
17007620a527SStefano Zampini     PetscInt  i;
17018361f951SStefano Zampini     PetscBool filter = pcbddc->detect_disconnected_filter;
17027a0e7b2cSstefano_zampini 
17037620a527SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
17049566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pcbddc->local_subs[i]));
17057620a527SStefano Zampini     }
17069566063dSJacob Faibussowitsch     PetscCall(PetscFree(pcbddc->local_subs));
17079566063dSJacob Faibussowitsch     PetscCall(PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv));
17089566063dSJacob Faibussowitsch     PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc,primalv));
17099566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&primalv));
17107620a527SStefano Zampini   }
17117620a527SStefano Zampini   /* early stage corner detection */
17127620a527SStefano Zampini   {
17137620a527SStefano Zampini     DM dm;
17147620a527SStefano Zampini 
17159566063dSJacob Faibussowitsch     PetscCall(MatGetDM(pc->pmat,&dm));
17164f819b78SStefano Zampini     if (!dm) {
17179566063dSJacob Faibussowitsch       PetscCall(PCGetDM(pc,&dm));
17184f819b78SStefano Zampini     }
17197620a527SStefano Zampini     if (dm) {
17207620a527SStefano Zampini       PetscBool isda;
17217620a527SStefano Zampini 
17229566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda));
17237620a527SStefano Zampini       if (isda) {
17247620a527SStefano Zampini         ISLocalToGlobalMapping l2l;
17257620a527SStefano Zampini         IS                     corners;
17267620a527SStefano Zampini         Mat                    lA;
17274f819b78SStefano Zampini         PetscBool              gl,lo;
17287620a527SStefano Zampini 
17294f819b78SStefano Zampini         {
17304f819b78SStefano Zampini           Vec               cvec;
17314f819b78SStefano Zampini           const PetscScalar *coords;
17324f819b78SStefano Zampini           PetscInt          dof,n,cdim;
17334f819b78SStefano Zampini           PetscBool         memc = PETSC_TRUE;
17344f819b78SStefano Zampini 
17359566063dSJacob Faibussowitsch           PetscCall(DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL));
17369566063dSJacob Faibussowitsch           PetscCall(DMGetCoordinates(dm,&cvec));
17379566063dSJacob Faibussowitsch           PetscCall(VecGetLocalSize(cvec,&n));
17389566063dSJacob Faibussowitsch           PetscCall(VecGetBlockSize(cvec,&cdim));
17394f819b78SStefano Zampini           n   /= cdim;
17409566063dSJacob Faibussowitsch           PetscCall(PetscFree(pcbddc->mat_graph->coords));
17419566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(dof*n*cdim,&pcbddc->mat_graph->coords));
17429566063dSJacob Faibussowitsch           PetscCall(VecGetArrayRead(cvec,&coords));
17434f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
17444f819b78SStefano Zampini           memc = PETSC_FALSE;
17454f819b78SStefano Zampini #endif
17464f819b78SStefano Zampini           if (dof != 1) memc = PETSC_FALSE;
17474f819b78SStefano Zampini           if (memc) {
17489566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(pcbddc->mat_graph->coords,coords,cdim*n*dof));
17494f819b78SStefano Zampini           } else { /* BDDC graph does not use any blocked information, we need to replicate the data */
17504f819b78SStefano Zampini             PetscReal *bcoords = pcbddc->mat_graph->coords;
17514f819b78SStefano Zampini             PetscInt  i, b, d;
17524f819b78SStefano Zampini 
17534f819b78SStefano Zampini             for (i=0;i<n;i++) {
17544f819b78SStefano Zampini               for (b=0;b<dof;b++) {
17554f819b78SStefano Zampini                 for (d=0;d<cdim;d++) {
17564f819b78SStefano Zampini                   bcoords[i*dof*cdim + b*cdim + d] = PetscRealPart(coords[i*cdim+d]);
17574f819b78SStefano Zampini                 }
17584f819b78SStefano Zampini               }
17594f819b78SStefano Zampini             }
17604f819b78SStefano Zampini           }
17619566063dSJacob Faibussowitsch           PetscCall(VecRestoreArrayRead(cvec,&coords));
17624f819b78SStefano Zampini           pcbddc->mat_graph->cdim  = cdim;
17634f819b78SStefano Zampini           pcbddc->mat_graph->cnloc = dof*n;
17644f819b78SStefano Zampini           pcbddc->mat_graph->cloc  = PETSC_FALSE;
17654f819b78SStefano Zampini         }
17669566063dSJacob Faibussowitsch         PetscCall(DMDAGetSubdomainCornersIS(dm,&corners));
17679566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(pc->pmat,&lA));
17689566063dSJacob Faibussowitsch         PetscCall(MatGetLocalToGlobalMapping(lA,&l2l,NULL));
17699566063dSJacob Faibussowitsch         PetscCall(MatISRestoreLocalMat(pc->pmat,&lA));
17704f819b78SStefano Zampini         lo   = (PetscBool)(l2l && corners);
17711c2dc1cbSBarry Smith         PetscCall(MPIU_Allreduce(&lo,&gl,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc)));
17724f819b78SStefano Zampini         if (gl) { /* From PETSc's DMDA */
17737620a527SStefano Zampini           const PetscInt    *idx;
177472ed36d8SStefano Zampini           PetscInt          dof,bs,*idxout,n;
17757620a527SStefano Zampini 
17769566063dSJacob Faibussowitsch           PetscCall(DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL));
17779566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetBlockSize(l2l,&bs));
17789566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(corners,&n));
17799566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(corners,&idx));
178072ed36d8SStefano Zampini           if (bs == dof) {
17819566063dSJacob Faibussowitsch             PetscCall(PetscMalloc1(n,&idxout));
17829566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout));
178372ed36d8SStefano Zampini           } else { /* the original DMDA local-to-local map have been modified */
178472ed36d8SStefano Zampini             PetscInt i,d;
178572ed36d8SStefano Zampini 
17869566063dSJacob Faibussowitsch             PetscCall(PetscMalloc1(dof*n,&idxout));
178772ed36d8SStefano Zampini             for (i=0;i<n;i++) for (d=0;d<dof;d++) idxout[dof*i+d] = dof*idx[i]+d;
17889566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingApply(l2l,dof*n,idxout,idxout));
178972ed36d8SStefano Zampini 
179072ed36d8SStefano Zampini             bs = 1;
179172ed36d8SStefano Zampini             n *= dof;
179272ed36d8SStefano Zampini           }
17939566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(corners,&idx));
17949566063dSJacob Faibussowitsch           PetscCall(DMDARestoreSubdomainCornersIS(dm,&corners));
17959566063dSJacob Faibussowitsch           PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners));
17969566063dSJacob Faibussowitsch           PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc,corners));
17979566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&corners));
17981c7a958bSStefano Zampini           pcbddc->corner_selected  = PETSC_TRUE;
17994f819b78SStefano Zampini           pcbddc->corner_selection = PETSC_TRUE;
18004f819b78SStefano Zampini         }
18014f819b78SStefano Zampini         if (corners) {
18029566063dSJacob Faibussowitsch           PetscCall(DMDARestoreSubdomainCornersIS(dm,&corners));
18037620a527SStefano Zampini         }
18047620a527SStefano Zampini       }
18057620a527SStefano Zampini     }
18067620a527SStefano Zampini   }
18071c7a958bSStefano Zampini   if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) {
18081c7a958bSStefano Zampini     DM dm;
18091c7a958bSStefano Zampini 
18109566063dSJacob Faibussowitsch     PetscCall(MatGetDM(pc->pmat,&dm));
18114f819b78SStefano Zampini     if (!dm) {
18129566063dSJacob Faibussowitsch       PetscCall(PCGetDM(pc,&dm));
18131c7a958bSStefano Zampini     }
18144f819b78SStefano Zampini     if (dm) { /* this can get very expensive, I need to find a faster alternative */
18151c7a958bSStefano Zampini       Vec            vcoords;
18161c7a958bSStefano Zampini       PetscSection   section;
18171c7a958bSStefano Zampini       PetscReal      *coords;
18181c7a958bSStefano Zampini       PetscInt       d,cdim,nl,nf,**ctxs;
18191c7a958bSStefano Zampini       PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
182051ab8ad6SStefano Zampini       /* debug coordinates */
182151ab8ad6SStefano Zampini       PetscViewer       viewer;
182251ab8ad6SStefano Zampini       PetscBool         flg;
182351ab8ad6SStefano Zampini       PetscViewerFormat format;
182451ab8ad6SStefano Zampini       const char        *prefix;
18251c7a958bSStefano Zampini 
18269566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateDim(dm,&cdim));
18279566063dSJacob Faibussowitsch       PetscCall(DMGetLocalSection(dm,&section));
18289566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(section,&nf));
18299566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(dm,&vcoords));
18309566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(vcoords,&nl));
18319566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl*cdim,&coords));
18329566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(nf,&funcs,nf,&ctxs));
18339566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nf,&ctxs[0]));
18341c7a958bSStefano Zampini       for (d=0;d<nf;d++) funcs[d] = func_coords_private;
18351c7a958bSStefano Zampini       for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1;
183651ab8ad6SStefano Zampini 
183751ab8ad6SStefano Zampini       /* debug coordinates */
183851ab8ad6SStefano Zampini       PetscCall(PCGetOptionsPrefix(pc,&prefix));
183951ab8ad6SStefano Zampini       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)vcoords),((PetscObject)vcoords)->options,prefix,"-pc_bddc_coords_vec_view",&viewer,&format,&flg));
184051ab8ad6SStefano Zampini       if (flg) PetscCall(PetscViewerPushFormat(viewer,format));
18411c7a958bSStefano Zampini       for (d=0;d<cdim;d++) {
18421c7a958bSStefano Zampini         PetscInt          i;
18431c7a958bSStefano Zampini         const PetscScalar *v;
184451ab8ad6SStefano Zampini         char              name[16];
18451c7a958bSStefano Zampini 
18461c7a958bSStefano Zampini         for (i=0;i<nf;i++) ctxs[i][0] = d;
184751ab8ad6SStefano Zampini         PetscCall(PetscSNPrintf(name,sizeof(name),"bddc_coords_%d",(int)d));
184851ab8ad6SStefano Zampini         PetscCall(PetscObjectSetName((PetscObject)vcoords,name));
18499566063dSJacob Faibussowitsch         PetscCall(DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords));
185051ab8ad6SStefano Zampini         if (flg) PetscCall(VecView(vcoords,viewer));
18519566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(vcoords,&v));
18521c7a958bSStefano Zampini         for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]);
18539566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(vcoords,&v));
18541c7a958bSStefano Zampini       }
18559566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&vcoords));
18569566063dSJacob Faibussowitsch       PetscCall(PCSetCoordinates(pc,cdim,nl,coords));
18579566063dSJacob Faibussowitsch       PetscCall(PetscFree(coords));
18589566063dSJacob Faibussowitsch       PetscCall(PetscFree(ctxs[0]));
18599566063dSJacob Faibussowitsch       PetscCall(PetscFree2(funcs,ctxs));
186051ab8ad6SStefano Zampini       if (flg) {
186151ab8ad6SStefano Zampini         PetscCall(PetscViewerPopFormat(viewer));
186251ab8ad6SStefano Zampini         PetscCall(PetscViewerDestroy(&viewer));
186351ab8ad6SStefano Zampini       }
18641c7a958bSStefano Zampini     }
18651c7a958bSStefano Zampini   }
18667a0e7b2cSstefano_zampini   PetscFunctionReturn(0);
18677a0e7b2cSstefano_zampini }
18687a0e7b2cSstefano_zampini 
18697a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is)
18707a0e7b2cSstefano_zampini {
18717a0e7b2cSstefano_zampini   Mat_IS          *matis = (Mat_IS*)(pc->pmat->data);
18727a0e7b2cSstefano_zampini   IS              nis;
18737a0e7b2cSstefano_zampini   const PetscInt  *idxs;
18747a0e7b2cSstefano_zampini   PetscInt        i,nd,n = matis->A->rmap->n,*nidxs,nnd;
18757a0e7b2cSstefano_zampini 
18767a0e7b2cSstefano_zampini   PetscFunctionBegin;
18777827d75bSBarry Smith   PetscCheck(mop == MPI_LAND || mop == MPI_LOR,PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR");
18787a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18797a0e7b2cSstefano_zampini     /* init rootdata with true */
18801bd50df1SStefano Zampini     for (i=0;i<pc->pmat->rmap->n;i++) matis->sf_rootdata[i] = 1;
18817a0e7b2cSstefano_zampini   } else {
18829566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n));
18837a0e7b2cSstefano_zampini   }
18849566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_leafdata,n));
18859566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(*is,&nd));
18869566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(*is,&idxs));
18877a0e7b2cSstefano_zampini   for (i=0;i<nd;i++)
18887a0e7b2cSstefano_zampini     if (-1 < idxs[i] && idxs[i] < n)
18891bd50df1SStefano Zampini       matis->sf_leafdata[idxs[i]] = 1;
18909566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(*is,&idxs));
18919566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,mop));
18929566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,mop));
18939566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
18949566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
18957a0e7b2cSstefano_zampini   if (mop == MPI_LAND) {
18969566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nd,&nidxs));
18977a0e7b2cSstefano_zampini   } else {
18989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&nidxs));
18997a0e7b2cSstefano_zampini   }
19007a0e7b2cSstefano_zampini   for (i=0,nnd=0;i<n;i++)
19011bd50df1SStefano Zampini     if (matis->sf_leafdata[i])
19027a0e7b2cSstefano_zampini       nidxs[nnd++] = i;
19039566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis));
19049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(is));
19057a0e7b2cSstefano_zampini   *is  = nis;
19061f4df5f7SStefano Zampini   PetscFunctionReturn(0);
19071f4df5f7SStefano Zampini }
19081f4df5f7SStefano Zampini 
19093e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
19103e589ea0SStefano Zampini {
19113e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
19123e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
19133e589ea0SStefano Zampini 
19143e589ea0SStefano Zampini   PetscFunctionBegin;
19153e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
19163e589ea0SStefano Zampini     PetscFunctionReturn(0);
19173e589ea0SStefano Zampini   }
19183e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19193e589ea0SStefano Zampini     Vec swap;
19203e589ea0SStefano Zampini 
19219566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change));
19223e589ea0SStefano Zampini     swap = pcbddc->work_change;
19233e589ea0SStefano Zampini     pcbddc->work_change = r;
19243e589ea0SStefano Zampini     r = swap;
19253e589ea0SStefano Zampini   }
19269566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
19279566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
19289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19299566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
19309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19319566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
19329566063dSJacob Faibussowitsch   PetscCall(VecSet(z,0.));
19339566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
19349566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
19353e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1936f913dca9SStefano Zampini     pcbddc->work_change = r;
19379566063dSJacob Faibussowitsch     PetscCall(VecCopy(z,pcbddc->work_change));
19389566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z));
19393e589ea0SStefano Zampini   }
19403e589ea0SStefano Zampini   PetscFunctionReturn(0);
19413e589ea0SStefano Zampini }
19423e589ea0SStefano Zampini 
1943a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1944a3df083aSStefano Zampini {
1945a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1946a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1947a3df083aSStefano Zampini 
1948a3df083aSStefano Zampini   PetscFunctionBegin;
19499566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(A,&ctx));
1950a3df083aSStefano Zampini   if (transpose) {
1951a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1952a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1953a3df083aSStefano Zampini   } else {
1954a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1955a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1956a3df083aSStefano Zampini   }
1957a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1958a3df083aSStefano Zampini   if (apply_right) {
1959a3df083aSStefano Zampini     const PetscScalar *ax;
1960a3df083aSStefano Zampini     PetscInt          nl,i;
1961a3df083aSStefano Zampini 
19629566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(x,&nl));
19639566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&ax));
19649566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(ctx->work,ax,nl));
19659566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&ax));
1966a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1967a3df083aSStefano Zampini       PetscScalar    sum,val;
1968a3df083aSStefano Zampini       const PetscInt *idxs;
1969a3df083aSStefano Zampini       PetscInt       nz,j;
19709566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz));
19719566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs));
1972a3df083aSStefano Zampini       sum = 0.;
1973a3df083aSStefano Zampini       if (ctx->apply_p0) {
1974a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1975a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1976a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1977a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1978a3df083aSStefano Zampini         }
1979a3df083aSStefano Zampini       } else {
1980a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1981a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1982a3df083aSStefano Zampini         }
1983a3df083aSStefano Zampini       }
1984a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
19859566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs));
1986a3df083aSStefano Zampini     }
19879566063dSJacob Faibussowitsch     PetscCall(VecPlaceArray(x,ctx->work));
1988a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1989a3df083aSStefano Zampini   }
1990a3df083aSStefano Zampini   if (transpose) {
19919566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(ctx->A,x,y));
1992a3df083aSStefano Zampini   } else {
19939566063dSJacob Faibussowitsch     PetscCall(MatMult(ctx->A,x,y));
1994a3df083aSStefano Zampini   }
1995a3df083aSStefano Zampini   if (reset_x) {
19969566063dSJacob Faibussowitsch     PetscCall(VecResetArray(x));
1997a3df083aSStefano Zampini   }
1998a3df083aSStefano Zampini   if (apply_left) {
1999a3df083aSStefano Zampini     PetscScalar *ay;
2000a3df083aSStefano Zampini     PetscInt    i;
2001a3df083aSStefano Zampini 
20029566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&ay));
2003a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
2004a3df083aSStefano Zampini       PetscScalar    sum,val;
2005a3df083aSStefano Zampini       const PetscInt *idxs;
2006a3df083aSStefano Zampini       PetscInt       nz,j;
20079566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz));
20089566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs));
2009a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
2010a3df083aSStefano Zampini       if (ctx->apply_p0) {
2011a3df083aSStefano Zampini         sum = 0.;
2012a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2013a3df083aSStefano Zampini           sum += ay[idxs[j]];
2014a3df083aSStefano Zampini           ay[idxs[j]] += val;
2015a3df083aSStefano Zampini         }
2016a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
2017a3df083aSStefano Zampini       } else {
2018a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
2019a3df083aSStefano Zampini           ay[idxs[j]] += val;
2020a3df083aSStefano Zampini         }
2021a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
2022a3df083aSStefano Zampini       }
20239566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs));
2024a3df083aSStefano Zampini     }
20259566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&ay));
2026a3df083aSStefano Zampini   }
2027a3df083aSStefano Zampini   PetscFunctionReturn(0);
2028a3df083aSStefano Zampini }
2029a3df083aSStefano Zampini 
2030a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
2031a3df083aSStefano Zampini {
2032a3df083aSStefano Zampini   PetscFunctionBegin;
20339566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE));
2034a3df083aSStefano Zampini   PetscFunctionReturn(0);
2035a3df083aSStefano Zampini }
2036a3df083aSStefano Zampini 
2037a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
2038a3df083aSStefano Zampini {
2039a3df083aSStefano Zampini   PetscFunctionBegin;
20409566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE));
2041a3df083aSStefano Zampini   PetscFunctionReturn(0);
2042a3df083aSStefano Zampini }
2043a3df083aSStefano Zampini 
2044a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
2045a3df083aSStefano Zampini {
2046a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
2047a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
2048a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
2049a3df083aSStefano Zampini 
2050a3df083aSStefano Zampini   PetscFunctionBegin;
2051a3df083aSStefano Zampini   if (!restore) {
20521dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
2053a3df083aSStefano Zampini     PetscScalar        *work;
2054b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
2055a3df083aSStefano Zampini 
205628b400f6SJacob Faibussowitsch     PetscCheck(!pcbddc->benign_original_mat,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
20579a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
20589566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n,&work));
20599566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF,&A_IB));
20609566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE));
20619566063dSJacob Faibussowitsch     PetscCall(MatSetType(A_IB,MATSHELL));
20629566063dSJacob Faibussowitsch     PetscCall(MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private));
20639566063dSJacob Faibussowitsch     PetscCall(MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private));
20649566063dSJacob Faibussowitsch     PetscCall(PetscNew(&ctx));
20659566063dSJacob Faibussowitsch     PetscCall(MatShellSetContext(A_IB,ctx));
2066a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
2067a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
2068a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
2069a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
2070059032f7SStefano Zampini     if (reuse) {
2071a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
20721dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
2073059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
2074059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
2075059032f7SStefano Zampini       PetscInt               i;
2076059032f7SStefano Zampini 
20779566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D));
20789566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs));
2079059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20809566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]));
2081059032f7SStefano Zampini       }
20829566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&N_to_D));
20831dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
2084059032f7SStefano Zampini     }
2085a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
2086a3df083aSStefano Zampini     ctx->work = work;
20879566063dSJacob Faibussowitsch     PetscCall(MatSetUp(A_IB));
20889566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY));
20899566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY));
2090a3df083aSStefano Zampini     pcis->A_IB = A_IB;
2091a3df083aSStefano Zampini 
2092a3df083aSStefano Zampini     /* A_BI as A_IB^T */
20939566063dSJacob Faibussowitsch     PetscCall(MatCreateTranspose(A_IB,&A_BI));
2094a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
2095a3df083aSStefano Zampini     pcis->A_BI = A_BI;
2096a3df083aSStefano Zampini   } else {
20971dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
20981dd7afcfSStefano Zampini       PetscFunctionReturn(0);
20991dd7afcfSStefano Zampini     }
21009566063dSJacob Faibussowitsch     PetscCall(MatShellGetContext(pcis->A_IB,&ctx));
21019566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
2102a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
21031dd7afcfSStefano Zampini     ctx->A = NULL;
21049566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
21051dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
21061dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
21071dd7afcfSStefano Zampini     if (ctx->free) {
2108059032f7SStefano Zampini       PetscInt i;
21091dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
21109566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&ctx->benign_zerodiag_subs[i]));
2111059032f7SStefano Zampini       }
21129566063dSJacob Faibussowitsch       PetscCall(PetscFree(ctx->benign_zerodiag_subs));
2113059032f7SStefano Zampini     }
21149566063dSJacob Faibussowitsch     PetscCall(PetscFree(ctx->work));
21159566063dSJacob Faibussowitsch     PetscCall(PetscFree(ctx));
2116a3df083aSStefano Zampini   }
2117a3df083aSStefano Zampini   PetscFunctionReturn(0);
2118a3df083aSStefano Zampini }
2119a3df083aSStefano Zampini 
2120a3df083aSStefano Zampini /* used just in bddc debug mode */
2121a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
2122a3df083aSStefano Zampini {
2123a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2124a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
2125a3df083aSStefano Zampini   Mat            An;
2126a3df083aSStefano Zampini 
2127a3df083aSStefano Zampini   PetscFunctionBegin;
21289566063dSJacob Faibussowitsch   PetscCall(MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An));
21299566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL));
2130a3df083aSStefano Zampini   if (is1) {
21319566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B));
21329566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&An));
2133a3df083aSStefano Zampini   } else {
2134a3df083aSStefano Zampini     *B = An;
2135a3df083aSStefano Zampini   }
2136a3df083aSStefano Zampini   PetscFunctionReturn(0);
2137a3df083aSStefano Zampini }
2138a3df083aSStefano Zampini 
21391cf9b237SStefano Zampini /* TODO: add reuse flag */
21401cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
21411cf9b237SStefano Zampini {
21421cf9b237SStefano Zampini   Mat            Bt;
21431cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
21441cf9b237SStefano Zampini   const PetscInt *ii,*ij;
21451cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
21461cf9b237SStefano Zampini   PetscBool      flg_row;
21471cf9b237SStefano Zampini 
21481cf9b237SStefano Zampini   PetscFunctionBegin;
21499566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&n,&m));
21509566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row));
21519566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(A,&a));
21521cf9b237SStefano Zampini   nnz = n;
21531cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
21541cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
21551cf9b237SStefano Zampini   }
21569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n+1,&bii));
21579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&bij));
21589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&bdata));
21591cf9b237SStefano Zampini   nnz = 0;
21601cf9b237SStefano Zampini   bii[0] = 0;
21611cf9b237SStefano Zampini   for (i=0;i<n;i++) {
21621cf9b237SStefano Zampini     PetscInt j;
21631cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
21641cf9b237SStefano Zampini       PetscScalar entry = a[j];
21653272d46bSStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) {
21661cf9b237SStefano Zampini         bij[nnz] = ij[j];
21671cf9b237SStefano Zampini         bdata[nnz] = entry;
21681cf9b237SStefano Zampini         nnz++;
21691cf9b237SStefano Zampini       }
21701cf9b237SStefano Zampini     }
21711cf9b237SStefano Zampini     bii[i+1] = nnz;
21721cf9b237SStefano Zampini   }
21739566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(A,&a));
21749566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt));
21759566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row));
21761cf9b237SStefano Zampini   {
21771cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
21781cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
21791cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
21801cf9b237SStefano Zampini   }
21813272d46bSStefano Zampini   if (*B == A) {
21829566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
21833272d46bSStefano Zampini   }
21841cf9b237SStefano Zampini   *B = Bt;
21851cf9b237SStefano Zampini   PetscFunctionReturn(0);
21861cf9b237SStefano Zampini }
21871cf9b237SStefano Zampini 
21888361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv)
21894f1b2e48SStefano Zampini {
2190c80a6c00SStefano Zampini   Mat                    B = NULL;
2191c80a6c00SStefano Zampini   DM                     dm;
21924f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
21934f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
21944f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2195c80a6c00SStefano Zampini   PetscInt               *xadj_filtered = NULL,*adjncy_filtered = NULL;
21964f1b2e48SStefano Zampini   PetscInt               i,n;
21974f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2198c80a6c00SStefano Zampini   PetscBool              isplex = PETSC_FALSE;
21994f1b2e48SStefano Zampini 
22004f1b2e48SStefano Zampini   PetscFunctionBegin;
2201a2eca866SStefano Zampini   if (ncc) *ncc = 0;
2202a2eca866SStefano Zampini   if (cc) *cc = NULL;
2203a2eca866SStefano Zampini   if (primalv) *primalv = NULL;
22049566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&graph));
22059566063dSJacob Faibussowitsch   PetscCall(MatGetDM(pc->pmat,&dm));
22064f819b78SStefano Zampini   if (!dm) {
22079566063dSJacob Faibussowitsch     PetscCall(PCGetDM(pc,&dm));
2208c80a6c00SStefano Zampini   }
2209c80a6c00SStefano Zampini   if (dm) {
22109566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex));
2211c80a6c00SStefano Zampini   }
22128361f951SStefano Zampini   if (filter) isplex = PETSC_FALSE;
22138361f951SStefano Zampini 
2214c80a6c00SStefano Zampini   if (isplex) { /* this code has been modified from plexpartition.c */
2215c80a6c00SStefano Zampini     PetscInt       p, pStart, pEnd, a, adjSize, idx, size, nroots;
2216c80a6c00SStefano Zampini     PetscInt      *adj = NULL;
2217c80a6c00SStefano Zampini     IS             cellNumbering;
2218c80a6c00SStefano Zampini     const PetscInt *cellNum;
2219c80a6c00SStefano Zampini     PetscBool      useCone, useClosure;
2220c80a6c00SStefano Zampini     PetscSection   section;
2221c80a6c00SStefano Zampini     PetscSegBuffer adjBuffer;
2222c80a6c00SStefano Zampini     PetscSF        sfPoint;
2223c80a6c00SStefano Zampini 
22249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd));
22259566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
22269566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
2227c80a6c00SStefano Zampini     /* Build adjacency graph via a section/segbuffer */
22289566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section));
22299566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(section, pStart, pEnd));
22309566063dSJacob Faibussowitsch     PetscCall(PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer));
2231c80a6c00SStefano Zampini     /* Always use FVM adjacency to create partitioner graph */
22329566063dSJacob Faibussowitsch     PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure));
22339566063dSJacob Faibussowitsch     PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE));
22349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellNumbering(dm, &cellNumbering));
22359566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(cellNumbering, &cellNum));
2236c80a6c00SStefano Zampini     for (n = 0, p = pStart; p < pEnd; p++) {
2237c80a6c00SStefano Zampini       /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2238c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
2239c80a6c00SStefano Zampini       adjSize = PETSC_DETERMINE;
22409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
2241c80a6c00SStefano Zampini       for (a = 0; a < adjSize; ++a) {
2242c80a6c00SStefano Zampini         const PetscInt point = adj[a];
22435cef3d0dSStefano Zampini         if (pStart <= point && point < pEnd) {
2244c80a6c00SStefano Zampini           PetscInt *PETSC_RESTRICT pBuf;
22459566063dSJacob Faibussowitsch           PetscCall(PetscSectionAddDof(section, p, 1));
22469566063dSJacob Faibussowitsch           PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf));
2247c80a6c00SStefano Zampini           *pBuf = point;
2248c80a6c00SStefano Zampini         }
2249c80a6c00SStefano Zampini       }
2250c80a6c00SStefano Zampini       n++;
2251c80a6c00SStefano Zampini     }
22529566063dSJacob Faibussowitsch     PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure));
2253c80a6c00SStefano Zampini     /* Derive CSR graph from section/segbuffer */
22549566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(section));
22559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(section, &size));
22569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n+1, &xadj));
2257c80a6c00SStefano Zampini     for (idx = 0, p = pStart; p < pEnd; p++) {
2258c80a6c00SStefano Zampini       if (nroots > 0) {if (cellNum[p] < 0) continue;}
22599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, p, &(xadj[idx++])));
2260c80a6c00SStefano Zampini     }
2261c80a6c00SStefano Zampini     xadj[n] = size;
22629566063dSJacob Faibussowitsch     PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &adjncy));
2263c80a6c00SStefano Zampini     /* Clean up */
22649566063dSJacob Faibussowitsch     PetscCall(PetscSegBufferDestroy(&adjBuffer));
22659566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&section));
22669566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
2267c80a6c00SStefano Zampini     graph->xadj = xadj;
2268c80a6c00SStefano Zampini     graph->adjncy = adjncy;
2269c80a6c00SStefano Zampini   } else {
2270c80a6c00SStefano Zampini     Mat       A;
22718361f951SStefano Zampini     PetscBool isseqaij, flg_row;
2272c80a6c00SStefano Zampini 
22739566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->pmat,&A));
227463c961adSStefano Zampini     if (!A->rmap->N || !A->cmap->N) {
22759566063dSJacob Faibussowitsch       PetscCall(PCBDDCGraphDestroy(&graph));
227663c961adSStefano Zampini       PetscFunctionReturn(0);
227763c961adSStefano Zampini     }
22789566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij));
22794f1b2e48SStefano Zampini     if (!isseqaij && filter) {
22801cf9b237SStefano Zampini       PetscBool isseqdense;
22811cf9b237SStefano Zampini 
22829566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense));
22831cf9b237SStefano Zampini       if (!isseqdense) {
22849566063dSJacob Faibussowitsch         PetscCall(MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B));
22851cf9b237SStefano Zampini       } else { /* TODO: rectangular case and LDA */
22861cf9b237SStefano Zampini         PetscScalar *array;
22871cf9b237SStefano Zampini         PetscReal   chop=1.e-6;
22881cf9b237SStefano Zampini 
22899566063dSJacob Faibussowitsch         PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&B));
22909566063dSJacob Faibussowitsch         PetscCall(MatDenseGetArray(B,&array));
22919566063dSJacob Faibussowitsch         PetscCall(MatGetSize(B,&n,NULL));
22921cf9b237SStefano Zampini         for (i=0;i<n;i++) {
22931cf9b237SStefano Zampini           PetscInt j;
22941cf9b237SStefano Zampini           for (j=i+1;j<n;j++) {
22951cf9b237SStefano Zampini             PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
22961cf9b237SStefano Zampini             if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
22971cf9b237SStefano Zampini             if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
22981cf9b237SStefano Zampini           }
22991cf9b237SStefano Zampini         }
23009566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreArray(B,&array));
23019566063dSJacob Faibussowitsch         PetscCall(MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B));
23021cf9b237SStefano Zampini       }
23034f1b2e48SStefano Zampini     } else {
23049566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
23054f1b2e48SStefano Zampini       B = A;
23064f1b2e48SStefano Zampini     }
23079566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row));
23084f1b2e48SStefano Zampini 
23094f1b2e48SStefano Zampini     /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
23104f1b2e48SStefano Zampini     if (filter) {
23114f1b2e48SStefano Zampini       PetscScalar *data;
23124f1b2e48SStefano Zampini       PetscInt    j,cum;
23134f1b2e48SStefano Zampini 
23149566063dSJacob Faibussowitsch       PetscCall(PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered));
23159566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(B,&data));
23164f1b2e48SStefano Zampini       cum = 0;
23174f1b2e48SStefano Zampini       for (i=0;i<n;i++) {
23184f1b2e48SStefano Zampini         PetscInt t;
23194f1b2e48SStefano Zampini 
23204f1b2e48SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) {
23214f1b2e48SStefano Zampini           if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
23224f1b2e48SStefano Zampini             continue;
23234f1b2e48SStefano Zampini           }
23244f1b2e48SStefano Zampini           adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
23254f1b2e48SStefano Zampini         }
23264f1b2e48SStefano Zampini         t = xadj_filtered[i];
23274f1b2e48SStefano Zampini         xadj_filtered[i] = cum;
23284f1b2e48SStefano Zampini         cum += t;
23294f1b2e48SStefano Zampini       }
23309566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(B,&data));
23314f1b2e48SStefano Zampini       graph->xadj = xadj_filtered;
23324f1b2e48SStefano Zampini       graph->adjncy = adjncy_filtered;
23334f1b2e48SStefano Zampini     } else {
23344f1b2e48SStefano Zampini       graph->xadj = xadj;
23354f1b2e48SStefano Zampini       graph->adjncy = adjncy;
23364f1b2e48SStefano Zampini     }
2337c80a6c00SStefano Zampini   }
2338c80a6c00SStefano Zampini   /* compute local connected components using PCBDDCGraph */
23399566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy));
23409566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy));
23419566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_dummy));
23429566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT));
23439566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap_dummy));
23449566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL));
23459566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphComputeConnectedComponents(graph));
2346c80a6c00SStefano Zampini 
23474f1b2e48SStefano Zampini   /* partial clean up */
23489566063dSJacob Faibussowitsch   PetscCall(PetscFree2(xadj_filtered,adjncy_filtered));
2349c80a6c00SStefano Zampini   if (B) {
2350c80a6c00SStefano Zampini     PetscBool flg_row;
23519566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row));
23529566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
23534f1b2e48SStefano Zampini   }
2354c80a6c00SStefano Zampini   if (isplex) {
23559566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
23569566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
2357c80a6c00SStefano Zampini   }
23584f1b2e48SStefano Zampini 
23594f1b2e48SStefano Zampini   /* get back data */
2360c80a6c00SStefano Zampini   if (isplex) {
2361c80a6c00SStefano Zampini     if (ncc) *ncc = graph->ncc;
2362c80a6c00SStefano Zampini     if (cc || primalv) {
2363c80a6c00SStefano Zampini       Mat          A;
2364c80a6c00SStefano Zampini       PetscBT      btv,btvt;
2365c80a6c00SStefano Zampini       PetscSection subSection;
2366c80a6c00SStefano Zampini       PetscInt     *ids,cum,cump,*cids,*pids;
2367c80a6c00SStefano Zampini 
23689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSubdomainSection(dm,&subSection));
23699566063dSJacob Faibussowitsch       PetscCall(MatISGetLocalMat(pc->pmat,&A));
23709566063dSJacob Faibussowitsch       PetscCall(PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids));
23719566063dSJacob Faibussowitsch       PetscCall(PetscBTCreate(A->rmap->n,&btv));
23729566063dSJacob Faibussowitsch       PetscCall(PetscBTCreate(A->rmap->n,&btvt));
2373c80a6c00SStefano Zampini 
2374c80a6c00SStefano Zampini       cids[0] = 0;
2375c80a6c00SStefano Zampini       for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) {
2376c80a6c00SStefano Zampini         PetscInt j;
2377c80a6c00SStefano Zampini 
23789566063dSJacob Faibussowitsch         PetscCall(PetscBTMemzero(A->rmap->n,btvt));
2379c80a6c00SStefano Zampini         for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) {
2380c80a6c00SStefano Zampini           PetscInt k, size, *closure = NULL, cell = graph->queue[j];
2381c80a6c00SStefano Zampini 
23829566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure));
2383c80a6c00SStefano Zampini           for (k = 0; k < 2*size; k += 2) {
238420c3699dSStefano Zampini             PetscInt s, pp, p = closure[k], off, dof, cdof;
2385c80a6c00SStefano Zampini 
23869566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetConstraintDof(subSection,p,&cdof));
23879566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetOffset(subSection,p,&off));
23889566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetDof(subSection,p,&dof));
2389c80a6c00SStefano Zampini             for (s = 0; s < dof-cdof; s++) {
2390c80a6c00SStefano 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 */
2393c80a6c00SStefano Zampini             }
23949566063dSJacob Faibussowitsch             PetscCall(DMPlexGetTreeParent(dm,p,&pp,NULL));
239520c3699dSStefano Zampini             if (pp != p) {
23969566063dSJacob Faibussowitsch               PetscCall(PetscSectionGetConstraintDof(subSection,pp,&cdof));
23979566063dSJacob Faibussowitsch               PetscCall(PetscSectionGetOffset(subSection,pp,&off));
23989566063dSJacob Faibussowitsch               PetscCall(PetscSectionGetDof(subSection,pp,&dof));
239920c3699dSStefano Zampini               for (s = 0; s < dof-cdof; s++) {
240020c3699dSStefano Zampini                 if (PetscBTLookupSet(btvt,off+s)) continue;
2401e432b41dSStefano Zampini                 if (!PetscBTLookup(btv,off+s)) ids[cum++] = off+s;
2402e432b41dSStefano Zampini                 else pids[cump++] = off+s; /* cross-vertex */
240320c3699dSStefano Zampini               }
240420c3699dSStefano Zampini             }
2405c80a6c00SStefano Zampini           }
24069566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure));
2407c80a6c00SStefano Zampini         }
2408c80a6c00SStefano Zampini         cids[i+1] = cum;
2409c80a6c00SStefano Zampini         /* mark dofs as already assigned */
2410c80a6c00SStefano Zampini         for (j = cids[i]; j < cids[i+1]; j++) {
24119566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(btv,ids[j]));
2412c80a6c00SStefano Zampini         }
2413c80a6c00SStefano Zampini       }
2414c80a6c00SStefano Zampini       if (cc) {
24159566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(graph->ncc,&cc_n));
2416c80a6c00SStefano Zampini         for (i = 0; i < graph->ncc; i++) {
24179566063dSJacob Faibussowitsch           PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i]));
2418c80a6c00SStefano Zampini         }
2419c80a6c00SStefano Zampini         *cc = cc_n;
2420c80a6c00SStefano Zampini       }
2421c80a6c00SStefano Zampini       if (primalv) {
24229566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv));
2423c80a6c00SStefano Zampini       }
24249566063dSJacob Faibussowitsch       PetscCall(PetscFree3(ids,cids,pids));
24259566063dSJacob Faibussowitsch       PetscCall(PetscBTDestroy(&btv));
24269566063dSJacob Faibussowitsch       PetscCall(PetscBTDestroy(&btvt));
2427c80a6c00SStefano Zampini     }
2428c80a6c00SStefano Zampini   } else {
24291cf9b237SStefano Zampini     if (ncc) *ncc = graph->ncc;
24301cf9b237SStefano Zampini     if (cc) {
24319566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(graph->ncc,&cc_n));
24324f1b2e48SStefano Zampini       for (i=0;i<graph->ncc;i++) {
24339566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,graph->cptr[i+1]-graph->cptr[i],graph->queue+graph->cptr[i],PETSC_COPY_VALUES,&cc_n[i]));
24344f1b2e48SStefano Zampini       }
24354f1b2e48SStefano Zampini       *cc = cc_n;
24361cf9b237SStefano Zampini     }
2437c80a6c00SStefano Zampini   }
24384f1b2e48SStefano Zampini   /* clean up graph */
24390a545947SLisandro Dalcin   graph->xadj = NULL;
24400a545947SLisandro Dalcin   graph->adjncy = NULL;
24419566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphDestroy(&graph));
24424f1b2e48SStefano Zampini   PetscFunctionReturn(0);
24434f1b2e48SStefano Zampini }
24444f1b2e48SStefano Zampini 
24455408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
24465408967cSStefano Zampini {
24475408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24485408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2449dee84bffSStefano Zampini   IS             dirIS = NULL;
24504f1b2e48SStefano Zampini   PetscInt       i;
24515408967cSStefano Zampini 
24525408967cSStefano Zampini   PetscFunctionBegin;
24539566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS));
24545408967cSStefano Zampini   if (zerodiag) {
24555408967cSStefano Zampini     Mat            A;
24565408967cSStefano Zampini     Vec            vec3_N;
24575408967cSStefano Zampini     PetscScalar    *vals;
24585408967cSStefano Zampini     const PetscInt *idxs;
2459d12d3064SStefano Zampini     PetscInt       nz,*count;
24605408967cSStefano Zampini 
24615408967cSStefano Zampini     /* p0 */
24629566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_N,0.));
24639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n,&vals));
24649566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(zerodiag,&nz));
24659566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(zerodiag,&idxs));
24664f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
24679566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES));
24689566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec1_N));
24699566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec1_N));
24705408967cSStefano Zampini     /* v_I */
24719566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(pcis->vec2_N,NULL));
24725408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
24739566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES));
24749566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(zerodiag,&idxs));
24759566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcis->is_B_local,&idxs));
24765408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
24779566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES));
24789566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcis->is_B_local,&idxs));
24795408967cSStefano Zampini     if (dirIS) {
24805408967cSStefano Zampini       PetscInt n;
24815408967cSStefano Zampini 
24829566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS,&n));
24839566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS,&idxs));
24845408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
24859566063dSJacob Faibussowitsch       PetscCall(VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES));
24869566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS,&idxs));
24875408967cSStefano Zampini     }
24889566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec2_N));
24899566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec2_N));
24909566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_N,&vec3_N));
24919566063dSJacob Faibussowitsch     PetscCall(VecSet(vec3_N,0.));
24929566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->pmat,&A));
24939566063dSJacob Faibussowitsch     PetscCall(MatMult(A,pcis->vec1_N,vec3_N));
24949566063dSJacob Faibussowitsch     PetscCall(VecDot(vec3_N,pcis->vec2_N,&vals[0]));
24957827d75bSBarry 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]));
24969566063dSJacob Faibussowitsch     PetscCall(PetscFree(vals));
24979566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vec3_N));
2498d12d3064SStefano Zampini 
2499d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
25009566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(pcis->n,&count));
25019566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcis->is_B_local,&idxs));
2502d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
25039566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcis->is_B_local,&idxs));
25049566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(zerodiag,&idxs));
250563a3b9bcSJacob 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]);
25069566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(zerodiag,&idxs));
25079566063dSJacob Faibussowitsch     PetscCall(PetscFree(count));
25085408967cSStefano Zampini   }
25099566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&dirIS));
25105408967cSStefano Zampini 
25115408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
25129566063dSJacob Faibussowitsch   PetscCall(VecSetRandom(pcis->vec1_global,NULL));
25134f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
25149566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE));
25154f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
25169566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE));
2517f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2518f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
251963a3b9bcSJacob 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));
2520f2a566d8SStefano Zampini   }
25215408967cSStefano Zampini   PetscFunctionReturn(0);
25225408967cSStefano Zampini }
25235408967cSStefano Zampini 
25243b03f7bbSStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal)
2525339f8db1SStefano Zampini {
2526339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2527e432b41dSStefano Zampini   Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
25283b03f7bbSStefano Zampini   IS             pressures = NULL,zerodiag = NULL,*bzerodiag = NULL,zerodiag_save,*zerodiag_subs;
25293b03f7bbSStefano Zampini   PetscInt       nz,n,benign_n,bsp = 1;
25304edc6404Sstefano_zampini   PetscInt       *interior_dofs,n_interior_dofs,nneu;
25314edc6404Sstefano_zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag,checkb;
2532339f8db1SStefano Zampini 
2533339f8db1SStefano Zampini   PetscFunctionBegin;
25343b03f7bbSStefano Zampini   if (reuse) goto project_b0;
25359566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&pcbddc->benign_sf));
25369566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->benign_B0));
2537a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
25389566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[n]));
2539a3df083aSStefano Zampini   }
25409566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->benign_zerodiag_subs));
25413b03f7bbSStefano Zampini   has_null_pressures = PETSC_TRUE;
25423b03f7bbSStefano Zampini   have_null = PETSC_TRUE;
25433b03f7bbSStefano Zampini   /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided)
25443b03f7bbSStefano Zampini      Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field)
25454f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
25464f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
25471ae86dd6SStefano Zampini      since the local Schur complements are already SPD
25484f1b2e48SStefano Zampini   */
254940fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
25507fbe2174Sstefano_zampini     IS        iP = NULL;
25513b03f7bbSStefano Zampini     PetscInt  p,*pp;
25523b03f7bbSStefano Zampini     PetscBool flg;
25534f1b2e48SStefano Zampini 
25549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal,&pp));
25553b03f7bbSStefano Zampini     n    = pcbddc->n_ISForDofsLocal;
2556d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");
25579566063dSJacob Faibussowitsch     PetscCall(PetscOptionsIntArray("-pc_bddc_pressure_field","Field id for pressures",NULL,pp,&n,&flg));
2558d0609cedSBarry Smith     PetscOptionsEnd();
25593b03f7bbSStefano Zampini     if (!flg) {
25603b03f7bbSStefano Zampini       n = 1;
25613b03f7bbSStefano Zampini       pp[0] = pcbddc->n_ISForDofsLocal-1;
25623b03f7bbSStefano Zampini     }
25633b03f7bbSStefano Zampini 
25643b03f7bbSStefano Zampini     bsp = 0;
25653b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25663b03f7bbSStefano Zampini       PetscInt bs;
25673b03f7bbSStefano Zampini 
256863a3b9bcSJacob 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]);
25699566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs));
25703b03f7bbSStefano Zampini       bsp += bs;
25713b03f7bbSStefano Zampini     }
25729566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bsp,&bzerodiag));
25733b03f7bbSStefano Zampini     bsp  = 0;
25743b03f7bbSStefano Zampini     for (p=0;p<n;p++) {
25753b03f7bbSStefano Zampini       const PetscInt *idxs;
25763b03f7bbSStefano Zampini       PetscInt       b,bs,npl,*bidxs;
25773b03f7bbSStefano Zampini 
25789566063dSJacob Faibussowitsch       PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs));
25799566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]],&npl));
25809566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs));
25819566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(npl/bs,&bidxs));
25823b03f7bbSStefano Zampini       for (b=0;b<bs;b++) {
25833b03f7bbSStefano Zampini         PetscInt i;
25843b03f7bbSStefano Zampini 
25853b03f7bbSStefano Zampini         for (i=0;i<npl/bs;i++) bidxs[i] = idxs[bs*i+b];
25869566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,npl/bs,bidxs,PETSC_COPY_VALUES,&bzerodiag[bsp]));
25873b03f7bbSStefano Zampini         bsp++;
25883b03f7bbSStefano Zampini       }
25899566063dSJacob Faibussowitsch       PetscCall(PetscFree(bidxs));
25909566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs));
25913b03f7bbSStefano Zampini     }
25929566063dSJacob Faibussowitsch     PetscCall(ISConcatenate(PETSC_COMM_SELF,bsp,bzerodiag,&pressures));
25933b03f7bbSStefano Zampini 
25947fbe2174Sstefano_zampini     /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */
25959566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP));
25967fbe2174Sstefano_zampini     if (iP) {
25977fbe2174Sstefano_zampini       IS newpressures;
25987fbe2174Sstefano_zampini 
25999566063dSJacob Faibussowitsch       PetscCall(ISDifference(pressures,iP,&newpressures));
26009566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pressures));
26017fbe2174Sstefano_zampini       pressures = newpressures;
26027fbe2174Sstefano_zampini     }
26039566063dSJacob Faibussowitsch     PetscCall(ISSorted(pressures,&sorted));
260440fa8d13SStefano Zampini     if (!sorted) {
26059566063dSJacob Faibussowitsch       PetscCall(ISSort(pressures));
260640fa8d13SStefano Zampini     }
26079566063dSJacob Faibussowitsch     PetscCall(PetscFree(pp));
260840fa8d13SStefano Zampini   }
26093b03f7bbSStefano Zampini 
261097d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
26119566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(pcbddc->local_mat,&n,NULL));
261227b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
26139566063dSJacob Faibussowitsch   PetscCall(MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag));
26149566063dSJacob Faibussowitsch   PetscCall(ISSorted(zerodiag,&sorted));
2615339f8db1SStefano Zampini   if (!sorted) {
26169566063dSJacob Faibussowitsch     PetscCall(ISSort(zerodiag));
2617339f8db1SStefano Zampini   }
26189566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)zerodiag));
26194edc6404Sstefano_zampini   zerodiag_save = zerodiag;
26209566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(zerodiag,&nz));
26214f1b2e48SStefano Zampini   if (!nz) {
26224f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
26234f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
26249566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&zerodiag));
262540fa8d13SStefano Zampini   }
26264f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
26273b03f7bbSStefano Zampini 
26284f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
26294f1b2e48SStefano Zampini   zerodiag_subs    = NULL;
26303b03f7bbSStefano Zampini   benign_n         = 0;
26311f4df5f7SStefano Zampini   n_interior_dofs  = 0;
26321f4df5f7SStefano Zampini   interior_dofs    = NULL;
26334edc6404Sstefano_zampini   nneu             = 0;
26344edc6404Sstefano_zampini   if (pcbddc->NeumannBoundariesLocal) {
26359566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu));
26364edc6404Sstefano_zampini   }
26373369cb78Sstefano_zampini   checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level);
26384edc6404Sstefano_zampini   if (checkb) { /* need to compute interior nodes */
26391f4df5f7SStefano Zampini     PetscInt n,i,j;
26401f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
26411f4df5f7SStefano Zampini     PetscInt *iwork;
26421f4df5f7SStefano Zampini 
26439566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&n));
26449566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetInfo(matis->rmapping,&n_neigh,&neigh,&n_shared,&shared));
26459566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n,&iwork));
26469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&interior_dofs));
264790648384SStefano Zampini     for (i=1;i<n_neigh;i++)
26481f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
26491f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
26501f4df5f7SStefano Zampini     for (i=0;i<n;i++)
26511f4df5f7SStefano Zampini       if (!iwork[i])
26521f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
26539566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
26549566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreInfo(matis->rmapping,&n_neigh,&neigh,&n_shared,&shared));
26551f4df5f7SStefano Zampini   }
26564f1b2e48SStefano Zampini   if (has_null_pressures) {
26574f1b2e48SStefano Zampini     IS             *subs;
26584edc6404Sstefano_zampini     PetscInt       nsubs,i,j,nl;
26591f4df5f7SStefano Zampini     const PetscInt *idxs;
26601f4df5f7SStefano Zampini     PetscScalar    *array;
26611f4df5f7SStefano Zampini     Vec            *work;
26624f1b2e48SStefano Zampini 
26634f1b2e48SStefano Zampini     subs  = pcbddc->local_subs;
26644f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
26651f4df5f7SStefano 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) */
26664edc6404Sstefano_zampini     if (checkb) {
26679566063dSJacob Faibussowitsch       PetscCall(VecDuplicateVecs(matis->y,2,&work));
26689566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(zerodiag,&nl));
26699566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(zerodiag,&idxs));
26701f4df5f7SStefano Zampini       /* work[0] = 1_p */
26719566063dSJacob Faibussowitsch       PetscCall(VecSet(work[0],0.));
26729566063dSJacob Faibussowitsch       PetscCall(VecGetArray(work[0],&array));
26731f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
26749566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(work[0],&array));
26751f4df5f7SStefano Zampini       /* work[0] = 1_v */
26769566063dSJacob Faibussowitsch       PetscCall(VecSet(work[1],1.));
26779566063dSJacob Faibussowitsch       PetscCall(VecGetArray(work[1],&array));
26781f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
26799566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(work[1],&array));
26809566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(zerodiag,&idxs));
26811f4df5f7SStefano Zampini     }
26823b03f7bbSStefano Zampini 
26833b03f7bbSStefano Zampini     if (nsubs > 1 || bsp > 1) {
26843b03f7bbSStefano Zampini       IS       *is;
26853b03f7bbSStefano Zampini       PetscInt b,totb;
26863b03f7bbSStefano Zampini 
26873b03f7bbSStefano Zampini       totb  = bsp;
26883b03f7bbSStefano Zampini       is    = bsp > 1 ? bzerodiag : &zerodiag;
26893b03f7bbSStefano Zampini       nsubs = PetscMax(nsubs,1);
26909566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nsubs*totb,&zerodiag_subs));
26913b03f7bbSStefano Zampini       for (b=0;b<totb;b++) {
26924f1b2e48SStefano Zampini         for (i=0;i<nsubs;i++) {
26934f1b2e48SStefano Zampini           ISLocalToGlobalMapping l2g;
26944f1b2e48SStefano Zampini           IS                     t_zerodiag_subs;
26954f1b2e48SStefano Zampini           PetscInt               nl;
26964f1b2e48SStefano Zampini 
26973b03f7bbSStefano Zampini           if (subs) {
26989566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingCreateIS(subs[i],&l2g));
26993b03f7bbSStefano Zampini           } else {
27003b03f7bbSStefano Zampini             IS tis;
27013b03f7bbSStefano Zampini 
27029566063dSJacob Faibussowitsch             PetscCall(MatGetLocalSize(pcbddc->local_mat,&nl,NULL));
27039566063dSJacob Faibussowitsch             PetscCall(ISCreateStride(PETSC_COMM_SELF,nl,0,1,&tis));
27049566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingCreateIS(tis,&l2g));
27059566063dSJacob Faibussowitsch             PetscCall(ISDestroy(&tis));
27063b03f7bbSStefano Zampini           }
27079566063dSJacob Faibussowitsch           PetscCall(ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,is[b],&t_zerodiag_subs));
27089566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(t_zerodiag_subs,&nl));
27094f1b2e48SStefano Zampini           if (nl) {
27104f1b2e48SStefano Zampini             PetscBool valid = PETSC_TRUE;
27114f1b2e48SStefano Zampini 
27124edc6404Sstefano_zampini             if (checkb) {
27139566063dSJacob Faibussowitsch               PetscCall(VecSet(matis->x,0));
27149566063dSJacob Faibussowitsch               PetscCall(ISGetLocalSize(subs[i],&nl));
27159566063dSJacob Faibussowitsch               PetscCall(ISGetIndices(subs[i],&idxs));
27169566063dSJacob Faibussowitsch               PetscCall(VecGetArray(matis->x,&array));
27171f4df5f7SStefano Zampini               for (j=0;j<nl;j++) array[idxs[j]] = 1.;
27189566063dSJacob Faibussowitsch               PetscCall(VecRestoreArray(matis->x,&array));
27199566063dSJacob Faibussowitsch               PetscCall(ISRestoreIndices(subs[i],&idxs));
27209566063dSJacob Faibussowitsch               PetscCall(VecPointwiseMult(matis->x,work[0],matis->x));
27219566063dSJacob Faibussowitsch               PetscCall(MatMult(matis->A,matis->x,matis->y));
27229566063dSJacob Faibussowitsch               PetscCall(VecPointwiseMult(matis->y,work[1],matis->y));
27239566063dSJacob Faibussowitsch               PetscCall(VecGetArray(matis->y,&array));
27241f4df5f7SStefano Zampini               for (j=0;j<n_interior_dofs;j++) {
27251f4df5f7SStefano Zampini                 if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27261f4df5f7SStefano Zampini                   valid = PETSC_FALSE;
27271f4df5f7SStefano Zampini                   break;
27281f4df5f7SStefano Zampini                 }
27291f4df5f7SStefano Zampini               }
27309566063dSJacob Faibussowitsch               PetscCall(VecRestoreArray(matis->y,&array));
27311f4df5f7SStefano Zampini             }
27326632bad2Sstefano_zampini             if (valid && nneu) {
27336632bad2Sstefano_zampini               const PetscInt *idxs;
27341f4df5f7SStefano Zampini               PetscInt       nzb;
27351f4df5f7SStefano Zampini 
27369566063dSJacob Faibussowitsch               PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs));
27379566063dSJacob Faibussowitsch               PetscCall(ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL));
27389566063dSJacob Faibussowitsch               PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs));
27391f4df5f7SStefano Zampini               if (nzb) valid = PETSC_FALSE;
27401f4df5f7SStefano Zampini             }
27411f4df5f7SStefano Zampini             if (valid && pressures) {
27423b03f7bbSStefano Zampini               IS       t_pressure_subs,tmp;
27433b03f7bbSStefano Zampini               PetscInt i1,i2;
27443b03f7bbSStefano Zampini 
27459566063dSJacob Faibussowitsch               PetscCall(ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs));
27469566063dSJacob Faibussowitsch               PetscCall(ISEmbed(t_zerodiag_subs,t_pressure_subs,PETSC_TRUE,&tmp));
27479566063dSJacob Faibussowitsch               PetscCall(ISGetLocalSize(tmp,&i1));
27489566063dSJacob Faibussowitsch               PetscCall(ISGetLocalSize(t_zerodiag_subs,&i2));
27493b03f7bbSStefano Zampini               if (i2 != i1) valid = PETSC_FALSE;
27509566063dSJacob Faibussowitsch               PetscCall(ISDestroy(&t_pressure_subs));
27519566063dSJacob Faibussowitsch               PetscCall(ISDestroy(&tmp));
27524f1b2e48SStefano Zampini             }
27534f1b2e48SStefano Zampini             if (valid) {
27549566063dSJacob Faibussowitsch               PetscCall(ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[benign_n]));
27553b03f7bbSStefano Zampini               benign_n++;
27563b03f7bbSStefano Zampini             } else recompute_zerodiag = PETSC_TRUE;
27574f1b2e48SStefano Zampini           }
27589566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&t_zerodiag_subs));
27599566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingDestroy(&l2g));
27604f1b2e48SStefano Zampini         }
27613b03f7bbSStefano Zampini       }
27624f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
27634f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
27641f4df5f7SStefano Zampini 
27656632bad2Sstefano_zampini       if (nneu) valid = PETSC_FALSE;
27661f4df5f7SStefano Zampini       if (valid && pressures) {
27679566063dSJacob Faibussowitsch         PetscCall(ISEqual(pressures,zerodiag,&valid));
27684f1b2e48SStefano Zampini       }
27694edc6404Sstefano_zampini       if (valid && checkb) {
27709566063dSJacob Faibussowitsch         PetscCall(MatMult(matis->A,work[0],matis->x));
27719566063dSJacob Faibussowitsch         PetscCall(VecPointwiseMult(matis->x,work[1],matis->x));
27729566063dSJacob Faibussowitsch         PetscCall(VecGetArray(matis->x,&array));
27731f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
27741f4df5f7SStefano Zampini           if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
27751f4df5f7SStefano Zampini             valid = PETSC_FALSE;
27761f4df5f7SStefano Zampini             break;
27771f4df5f7SStefano Zampini           }
27781f4df5f7SStefano Zampini         }
27799566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(matis->x,&array));
27801f4df5f7SStefano Zampini       }
27814f1b2e48SStefano Zampini       if (valid) {
27823b03f7bbSStefano Zampini         benign_n = 1;
27839566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(benign_n,&zerodiag_subs));
27849566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)zerodiag));
27854f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
27864f1b2e48SStefano Zampini       }
27874f1b2e48SStefano Zampini     }
27884edc6404Sstefano_zampini     if (checkb) {
27899566063dSJacob Faibussowitsch       PetscCall(VecDestroyVecs(2,&work));
27904f1b2e48SStefano Zampini     }
27911f4df5f7SStefano Zampini   }
27929566063dSJacob Faibussowitsch   PetscCall(PetscFree(interior_dofs));
27934f1b2e48SStefano Zampini 
27943b03f7bbSStefano Zampini   if (!benign_n) {
2795b9b0e38cSStefano Zampini     PetscInt n;
2796b9b0e38cSStefano Zampini 
27979566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&zerodiag));
27984f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
27999566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pcbddc->local_mat,&n,NULL));
280076a58201SStefano Zampini     if (n) have_null = PETSC_FALSE;
2801b9b0e38cSStefano Zampini   }
28024f1b2e48SStefano Zampini 
28034f1b2e48SStefano Zampini   /* final check for null pressures */
28044f1b2e48SStefano Zampini   if (zerodiag && pressures) {
28059566063dSJacob Faibussowitsch     PetscCall(ISEqual(pressures,zerodiag,&have_null));
28064f1b2e48SStefano Zampini   }
28074f1b2e48SStefano Zampini 
28084f1b2e48SStefano Zampini   if (recompute_zerodiag) {
28099566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&zerodiag));
28103b03f7bbSStefano Zampini     if (benign_n == 1) {
28119566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)zerodiag_subs[0]));
28124f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
28134f1b2e48SStefano Zampini     } else {
28144f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
28154f1b2e48SStefano Zampini 
28164f1b2e48SStefano Zampini       nzn = 0;
28173b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28184f1b2e48SStefano Zampini         PetscInt ns;
28199566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(zerodiag_subs[i],&ns));
28204f1b2e48SStefano Zampini         nzn += ns;
28214f1b2e48SStefano Zampini       }
28229566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nzn,&new_idxs));
28234f1b2e48SStefano Zampini       nzn = 0;
28243b03f7bbSStefano Zampini       for (i=0;i<benign_n;i++) {
28254f1b2e48SStefano Zampini         PetscInt ns,*idxs;
28269566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(zerodiag_subs[i],&ns));
28279566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs));
28289566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(new_idxs+nzn,idxs,ns));
28299566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs));
28304f1b2e48SStefano Zampini         nzn += ns;
28314f1b2e48SStefano Zampini       }
28329566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(nzn,new_idxs));
28339566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag));
28344f1b2e48SStefano Zampini     }
28354f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
28364f1b2e48SStefano Zampini   }
28374f1b2e48SStefano Zampini 
28383b03f7bbSStefano Zampini   /* determines if the coarse solver will be singular or not */
28391c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc)));
28403b03f7bbSStefano Zampini 
2841669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2842a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2843a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2844a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2845a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2846a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2847a198735bSStefano Zampini 
28481f4df5f7SStefano Zampini     if (pressures) {
28491f4df5f7SStefano Zampini       isused = pressures;
28501f4df5f7SStefano Zampini     } else {
28514edc6404Sstefano_zampini       isused = zerodiag_save;
28521f4df5f7SStefano Zampini     }
28539566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL));
28549566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->pmat,&A));
28559566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A,&n,NULL));
28567827d75bSBarry 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");
2857a198735bSStefano Zampini     n_isused = 0;
2858a198735bSStefano Zampini     if (isused) {
28599566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(isused,&n_isused));
2860a198735bSStefano Zampini     }
28619566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc)));
2862a198735bSStefano Zampini     st = st-n_isused;
28631ae86dd6SStefano Zampini     if (n) {
2864a198735bSStefano Zampini       const PetscInt *gidxs;
2865a198735bSStefano Zampini 
28669566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp));
28679566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs));
2868a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
28699566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row));
28709566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col));
28719566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs));
28721ae86dd6SStefano Zampini     } else {
28739566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp));
28749566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row));
28759566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col));
2876a198735bSStefano Zampini     }
28779566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->pmat,NULL,&N));
28789566063dSJacob Faibussowitsch     PetscCall(ISGetSize(row,&M));
28799566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(row,&rl2g));
28809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(col,&cl2g));
28819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&row));
28829566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&col));
28839566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp));
28849566063dSJacob Faibussowitsch     PetscCall(MatSetType(pcbddc->divudotp,MATIS));
28859566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N));
28869566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g));
28879566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
28889566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
28899566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(pcbddc->divudotp,loc_divudotp));
28909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&loc_divudotp));
28919566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY));
28929566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY));
28931ae86dd6SStefano Zampini   }
28949566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag_save));
28959566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pressures));
28963b03f7bbSStefano Zampini   if (bzerodiag) {
28973b03f7bbSStefano Zampini     PetscInt i;
2898b3afcdbeSStefano Zampini 
28993b03f7bbSStefano Zampini     for (i=0;i<bsp;i++) {
29009566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&bzerodiag[i]));
29013b03f7bbSStefano Zampini     }
29029566063dSJacob Faibussowitsch     PetscCall(PetscFree(bzerodiag));
29033b03f7bbSStefano Zampini   }
29043b03f7bbSStefano Zampini   pcbddc->benign_n = benign_n;
29053b03f7bbSStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
29063b03f7bbSStefano Zampini 
29073b03f7bbSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
29083b03f7bbSStefano Zampini   have_null = (PetscBool)(!!pcbddc->benign_n);
29091c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
29103b03f7bbSStefano Zampini 
29113b03f7bbSStefano Zampini project_b0:
29129566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(pcbddc->local_mat,&n,NULL));
2913b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
29143b03f7bbSStefano Zampini   if (pcbddc->benign_n) {
29154f1b2e48SStefano Zampini     PetscInt i,s,*nnz;
29164f1b2e48SStefano Zampini 
2917339f8db1SStefano Zampini     /* local change of basis for pressures */
29189566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->benign_change));
29199566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change));
29209566063dSJacob Faibussowitsch     PetscCall(MatSetType(pcbddc->benign_change,MATAIJ));
29219566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE));
29229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&nnz));
2923aa0d93e9SStefano Zampini     for (i=0;i<n;i++) nnz[i] = 1; /* defaults to identity */
29244f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2925aa0d93e9SStefano Zampini       const PetscInt *idxs;
29264f1b2e48SStefano Zampini       PetscInt       nzs,j;
29274f1b2e48SStefano Zampini 
29289566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nzs));
29299566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i],&idxs));
29304f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
29314f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
29329566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],&idxs));
29334f1b2e48SStefano Zampini     }
29349566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz));
29359566063dSJacob Faibussowitsch     PetscCall(MatSetOption(pcbddc->benign_change,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
29369566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
2937aa0d93e9SStefano Zampini     /* set identity by default */
2938aa0d93e9SStefano Zampini     for (i=0;i<n;i++) {
29399566063dSJacob Faibussowitsch       PetscCall(MatSetValue(pcbddc->benign_change,i,i,1.,INSERT_VALUES));
2940339f8db1SStefano Zampini     }
29419566063dSJacob Faibussowitsch     PetscCall(PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0));
29429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(pcbddc->benign_n,&pcbddc->benign_p0_lidx,pcbddc->benign_n,&pcbddc->benign_p0_gidx,pcbddc->benign_n,&pcbddc->benign_p0));
2943339f8db1SStefano Zampini     /* set change on pressures */
29444f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
29454f1b2e48SStefano Zampini       PetscScalar    *array;
2946aa0d93e9SStefano Zampini       const PetscInt *idxs;
29474f1b2e48SStefano Zampini       PetscInt       nzs;
29484f1b2e48SStefano Zampini 
29499566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[s],&nzs));
29509566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[s],&idxs));
29514f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2952339f8db1SStefano Zampini         PetscScalar vals[2];
2953339f8db1SStefano Zampini         PetscInt    cols[2];
2954339f8db1SStefano Zampini 
2955339f8db1SStefano Zampini         cols[0] = idxs[i];
29564f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2957339f8db1SStefano Zampini         vals[0] = 1.;
2958b0f5fe93SStefano Zampini         vals[1] = 1.;
29599566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES));
2960339f8db1SStefano Zampini       }
29619566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nzs,&array));
29624f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
29634f1b2e48SStefano Zampini       array[nzs-1] = 1.;
29649566063dSJacob Faibussowitsch       PetscCall(MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES));
29654f1b2e48SStefano Zampini       /* store local idxs for p0 */
29664f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
29679566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[s],&idxs));
29689566063dSJacob Faibussowitsch       PetscCall(PetscFree(array));
29694f1b2e48SStefano Zampini     }
29709566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY));
29719566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY));
29723b03f7bbSStefano Zampini 
2973a3df083aSStefano Zampini     /* project if needed */
2974a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
29751dd7afcfSStefano Zampini       Mat M;
29761dd7afcfSStefano Zampini 
29779566063dSJacob Faibussowitsch       PetscCall(MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M));
29789566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->local_mat));
29799566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCompress(M,&pcbddc->local_mat));
29809566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M));
2981a3df083aSStefano Zampini     }
29824f1b2e48SStefano Zampini     /* store global idxs for p0 */
29839566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(matis->rmapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx));
2984339f8db1SStefano Zampini   }
2985339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2986339f8db1SStefano Zampini   PetscFunctionReturn(0);
2987339f8db1SStefano Zampini }
2988339f8db1SStefano Zampini 
2989015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2990efc2fbd9SStefano Zampini {
2991efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2992de9d7bd0SStefano Zampini   PetscScalar    *array;
2993efc2fbd9SStefano Zampini 
2994efc2fbd9SStefano Zampini   PetscFunctionBegin;
2995efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
29969566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf));
29979566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx));
2998efc2fbd9SStefano Zampini   }
2999de9d7bd0SStefano Zampini   if (get) {
30009566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(v,(const PetscScalar**)&array));
30019566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0,MPI_REPLACE));
30029566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0,MPI_REPLACE));
30039566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(v,(const PetscScalar**)&array));
3004de9d7bd0SStefano Zampini   } else {
30059566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v,&array));
30069566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPI_REPLACE));
30079566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPI_REPLACE));
30089566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v,&array));
3009efc2fbd9SStefano Zampini   }
3010efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
3011efc2fbd9SStefano Zampini }
3012efc2fbd9SStefano Zampini 
3013c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
3014c263805aSStefano Zampini {
3015c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3016c263805aSStefano Zampini 
3017c263805aSStefano Zampini   PetscFunctionBegin;
3018c263805aSStefano Zampini   /* TODO: add error checking
3019c263805aSStefano Zampini     - avoid nested pop (or push) calls.
3020c263805aSStefano Zampini     - cannot push before pop.
30211c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
3022c263805aSStefano Zampini   */
30234f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
3024efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
3025efc2fbd9SStefano Zampini   }
3026c263805aSStefano Zampini   if (pop) {
3027a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
30284f1b2e48SStefano Zampini       IS       is_p0;
30294f1b2e48SStefano Zampini       MatReuse reuse;
3030c263805aSStefano Zampini 
3031c263805aSStefano Zampini       /* extract B_0 */
30324f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
30334f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
30344f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
30354f1b2e48SStefano Zampini       }
30369566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0));
30379566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0));
3038c263805aSStefano Zampini       /* remove rows and cols from local problem */
30399566063dSJacob Faibussowitsch       PetscCall(MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE));
30409566063dSJacob Faibussowitsch       PetscCall(MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE));
30419566063dSJacob Faibussowitsch       PetscCall(MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL));
30429566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is_p0));
3043a3df083aSStefano Zampini     } else {
3044a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
3045a3df083aSStefano Zampini       PetscScalar *vals;
3046a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
3047a3df083aSStefano Zampini 
30489566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(matis->y,&n));
30499566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(n,&idxs_ins,n,&vals));
3050a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
30510b5adadeSStefano Zampini         PetscInt *nnz;
30529566063dSJacob Faibussowitsch         PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0));
30539566063dSJacob Faibussowitsch         PetscCall(MatSetType(pcbddc->benign_B0,MATAIJ));
30549566063dSJacob Faibussowitsch         PetscCall(MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE));
30559566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(pcbddc->benign_n,&nnz));
3056331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
30579566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]));
3058331e053bSStefano Zampini           nnz[i] = n - nnz[i];
3059331e053bSStefano Zampini         }
30609566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz));
30619566063dSJacob Faibussowitsch         PetscCall(MatSetOption(pcbddc->benign_B0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
30629566063dSJacob Faibussowitsch         PetscCall(PetscFree(nnz));
3063331e053bSStefano Zampini       }
3064a3df083aSStefano Zampini 
3065a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3066a3df083aSStefano Zampini         PetscScalar *array;
3067a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
3068a3df083aSStefano Zampini 
30699566063dSJacob Faibussowitsch         PetscCall(VecSet(matis->x,0.));
30709566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz));
30719566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs));
3072a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
30739566063dSJacob Faibussowitsch         PetscCall(VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES));
30749566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(matis->x));
30759566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(matis->x));
30769566063dSJacob Faibussowitsch         PetscCall(VecSet(matis->y,0.));
30779566063dSJacob Faibussowitsch         PetscCall(MatMult(matis->A,matis->x,matis->y));
30789566063dSJacob Faibussowitsch         PetscCall(VecGetArray(matis->y,&array));
3079a3df083aSStefano Zampini         cum = 0;
3080a3df083aSStefano Zampini         for (j=0;j<n;j++) {
308122db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
3082a3df083aSStefano Zampini             vals[cum] = array[j];
3083a3df083aSStefano Zampini             idxs_ins[cum] = j;
3084a3df083aSStefano Zampini             cum++;
3085a3df083aSStefano Zampini           }
3086a3df083aSStefano Zampini         }
30879566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES));
30889566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(matis->y,&array));
30899566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs));
3090a3df083aSStefano Zampini       }
30919566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY));
30929566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY));
30939566063dSJacob Faibussowitsch       PetscCall(PetscFree2(idxs_ins,vals));
3094a3df083aSStefano Zampini     }
3095c263805aSStefano Zampini   } else { /* push */
3096a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
30974f1b2e48SStefano Zampini       PetscInt i;
30984f1b2e48SStefano Zampini 
30994f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
31004f1b2e48SStefano Zampini         PetscScalar *B0_vals;
31014f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
31024f1b2e48SStefano Zampini 
31039566063dSJacob Faibussowitsch         PetscCall(MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals));
31049566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES));
31059566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES));
31069566063dSJacob Faibussowitsch         PetscCall(MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES));
31079566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals));
31084f1b2e48SStefano Zampini       }
31099566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY));
31109566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY));
31116080607fSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!");
3112c263805aSStefano Zampini   }
3113c263805aSStefano Zampini   PetscFunctionReturn(0);
3114c263805aSStefano Zampini }
3115c263805aSStefano Zampini 
311608122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
3117b1b3d7a2SStefano Zampini {
3118b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
311908122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
312008122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
312108122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
312208122e43SStefano Zampini   PetscScalar     *work,lwork;
312308122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
312408122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
3125bd2a564bSStefano Zampini   PetscReal       *eigs,thresh,lthresh,uthresh;
31261b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
3127f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
312808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
312908122e43SStefano Zampini   PetscReal       *rwork;
313008122e43SStefano Zampini #endif
3131b1b3d7a2SStefano Zampini 
3132b1b3d7a2SStefano Zampini   PetscFunctionBegin;
313328b400f6SJacob Faibussowitsch   PetscCheck(sub_schurs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
313428b400f6SJacob Faibussowitsch   PetscCheck(sub_schurs->schur_explicit,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
313508401ef6SPierre Jolivet   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);
31369566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0));
313706a4e24aSStefano Zampini 
3138fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
31399566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
31409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
31419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n"));
31429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
3143fd14bc51SStefano Zampini   }
3144fd14bc51SStefano Zampini 
3145e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
314663a3b9bcSJacob 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));
3147e496cd5dSStefano Zampini   }
3148e496cd5dSStefano Zampini 
314908122e43SStefano Zampini   /* max size of subsets */
315008122e43SStefano Zampini   mss = 0;
315108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
315208122e43SStefano Zampini     PetscInt subset_size;
3153862806e4SStefano Zampini 
31549566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size));
315508122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
315608122e43SStefano Zampini   }
315708122e43SStefano Zampini 
315808122e43SStefano Zampini   /* min/max and threshold */
315908122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
3160f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
316108122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
3162f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
3163bd2a564bSStefano Zampini   if (nmin || !sub_schurs->is_posdef) { /* XXX */
3164f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
3165f6f667cfSStefano Zampini   }
316608122e43SStefano Zampini 
316708122e43SStefano Zampini   /* allocate lapack workspace */
316808122e43SStefano Zampini   cum = cum2 = 0;
316908122e43SStefano Zampini   maxneigs = 0;
317008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
317108122e43SStefano Zampini     PetscInt n,subset_size;
3172f6f667cfSStefano Zampini 
31739566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size));
317408122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
31759162d606SStefano Zampini     cum += subset_size;
31769162d606SStefano Zampini     cum2 += subset_size*n;
317708122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
317808122e43SStefano Zampini   }
31797ebab0bbSStefano Zampini   lwork = 0;
318008122e43SStefano Zampini   if (mss) {
3181bd2a564bSStefano Zampini     if (sub_schurs->is_symmetric) {
31827ebab0bbSStefano Zampini       PetscScalar  sdummy = 0.;
318308122e43SStefano Zampini       PetscBLASInt B_itype = 1;
31847ebab0bbSStefano Zampini       PetscBLASInt B_N = mss, idummy = 0;
31857ebab0bbSStefano Zampini       PetscReal    rdummy = 0.,zero = 0.0;
31864c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
318708122e43SStefano Zampini 
318808122e43SStefano Zampini       B_lwork = -1;
31897ebab0bbSStefano Zampini       /* some implementations may complain about NULL pointers, even if we are querying */
31907ebab0bbSStefano Zampini       S = &sdummy;
31917ebab0bbSStefano Zampini       St = &sdummy;
31927ebab0bbSStefano Zampini       eigs = &rdummy;
31937ebab0bbSStefano Zampini       eigv = &sdummy;
31947ebab0bbSStefano Zampini       B_iwork = &idummy;
31957ebab0bbSStefano Zampini       B_ifail = &idummy;
3196d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
31977ebab0bbSStefano Zampini       rwork = &rdummy;
3198d1710679SStefano Zampini #endif
31998bec7fa6SStefano Zampini       thresh = 1.0;
32009566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
320108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
320208122e43SStefano 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));
320308122e43SStefano Zampini #else
320408122e43SStefano 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));
320508122e43SStefano Zampini #endif
320608401ef6SPierre Jolivet       PetscCheck(B_ierr == 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
32079566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
3208bd2a564bSStefano Zampini     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
320908122e43SStefano Zampini   }
321008122e43SStefano Zampini 
321108122e43SStefano Zampini   nv = 0;
3212d62866d3SStefano 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) */
32139566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(sub_schurs->is_vertices,&nv));
321408122e43SStefano Zampini   }
32159566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork));
3216f6f667cfSStefano Zampini   if (allocated_S_St) {
32179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(mss*mss,&S,mss*mss,&St));
3218f6f667cfSStefano Zampini   }
32199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail));
322008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32219566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*mss,&rwork));
322208122e43SStefano Zampini #endif
3223d0609cedSBarry Smith   PetscCall(PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
32249162d606SStefano Zampini                          nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
32259162d606SStefano Zampini                          nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
322608122e43SStefano Zampini                          nv+cum,&pcbddc->adaptive_constraints_idxs,
3227d0609cedSBarry Smith                          nv+cum2,&pcbddc->adaptive_constraints_data));
32289566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->adaptive_constraints_n,nv+sub_schurs->n_subs));
322908122e43SStefano Zampini 
323008122e43SStefano Zampini   maxneigs = 0;
323172b8c272SStefano Zampini   cum = cumarray = 0;
32329162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
32339162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
3234d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
323508122e43SStefano Zampini     const PetscInt *idxs;
323608122e43SStefano Zampini 
32379566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(sub_schurs->is_vertices,&idxs));
323808122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
323908122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
324008122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
324108122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
32429162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
32439162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
324408122e43SStefano Zampini     }
32459566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(sub_schurs->is_vertices,&idxs));
324608122e43SStefano Zampini   }
324708122e43SStefano Zampini 
324808122e43SStefano Zampini   if (mss) { /* multilevel */
32499566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray));
32509566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray));
325108122e43SStefano Zampini   }
325208122e43SStefano Zampini 
3253bd2a564bSStefano Zampini   lthresh = pcbddc->adaptive_threshold[0];
3254bd2a564bSStefano Zampini   uthresh = pcbddc->adaptive_threshold[1];
325508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
325608122e43SStefano Zampini     const PetscInt *idxs;
32579d54b7f4SStefano Zampini     PetscReal      upper,lower;
3258862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
325908122e43SStefano Zampini     PetscBLASInt   B_N;
3260aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
3261bd2a564bSStefano Zampini     PetscBool      scal = PETSC_FALSE;
326208122e43SStefano Zampini 
32639d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
32649d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
3265bd2a564bSStefano Zampini       lower = uthresh;
32669d54b7f4SStefano 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     }
32719566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size));
32729566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(sub_schurs->is_subs[i],&idxs));
32739566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(subset_size,&B_N));
3274bd2a564bSStefano Zampini     /* this is experimental: we assume the dofs have been properly grouped to have
3275bd2a564bSStefano Zampini        the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */
3276bd2a564bSStefano Zampini     if (!sub_schurs->is_posdef) {
3277bd2a564bSStefano Zampini       Mat T;
3278bd2a564bSStefano Zampini 
3279bd2a564bSStefano Zampini       for (j=0;j<subset_size;j++) {
3280bd2a564bSStefano Zampini         if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) {
32819566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T));
32829566063dSJacob Faibussowitsch           PetscCall(MatScale(T,-1.0));
32839566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&T));
32849566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T));
32859566063dSJacob Faibussowitsch           PetscCall(MatScale(T,-1.0));
32869566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&T));
3287bd2a564bSStefano Zampini           if (sub_schurs->change_primal_sub) {
3288bd2a564bSStefano Zampini             PetscInt       nz,k;
3289bd2a564bSStefano Zampini             const PetscInt *idxs;
3290bd2a564bSStefano Zampini 
32919566063dSJacob Faibussowitsch             PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz));
32929566063dSJacob Faibussowitsch             PetscCall(ISGetIndices(sub_schurs->change_primal_sub[i],&idxs));
3293bd2a564bSStefano Zampini             for (k=0;k<nz;k++) {
3294bd2a564bSStefano Zampini               *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0;
3295bd2a564bSStefano Zampini               *(Starray + cumarray + idxs[k]*(subset_size+1))  = 0.0;
3296bd2a564bSStefano Zampini             }
32979566063dSJacob Faibussowitsch             PetscCall(ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs));
3298bd2a564bSStefano Zampini           }
3299bd2a564bSStefano Zampini           scal = PETSC_TRUE;
3300bd2a564bSStefano Zampini           break;
3301bd2a564bSStefano Zampini         }
3302bd2a564bSStefano Zampini       }
3303bd2a564bSStefano Zampini     }
3304bd2a564bSStefano Zampini 
3305f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3306bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
3307aff50787SStefano Zampini         PetscInt j,k;
3308580bdb30SBarry Smith         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */
33099566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(S,subset_size*subset_size));
33109566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(St,subset_size*subset_size));
331108122e43SStefano Zampini         }
331208122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
3313aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
3314aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
3315aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
3316aff50787SStefano Zampini           }
331708122e43SStefano Zampini         }
331808122e43SStefano Zampini       } else {
33199566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
33209566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
332108122e43SStefano Zampini       }
33228bec7fa6SStefano Zampini     } else {
3323f6f667cfSStefano Zampini       S = Sarray + cumarray;
3324f6f667cfSStefano Zampini       St = Starray + cumarray;
33258bec7fa6SStefano Zampini     }
3326aff50787SStefano Zampini     /* see if we can save some work */
3327b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
33289566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(S,St,subset_size*subset_size,&same_data));
3329aff50787SStefano Zampini     }
3330aff50787SStefano Zampini 
3331b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
3332aff50787SStefano Zampini       B_neigs = 0;
3333aff50787SStefano Zampini     } else {
3334bd2a564bSStefano Zampini       if (sub_schurs->is_symmetric) {
333508122e43SStefano Zampini         PetscBLASInt B_itype = 1;
3336f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
33374c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
33389552c7c7SStefano Zampini         PetscInt     nmin_s;
3339bd2a564bSStefano Zampini         PetscBool    compute_range;
3340bd2a564bSStefano Zampini 
33419036ceccSStefano Zampini         B_neigs = 0;
3342bd2a564bSStefano Zampini         compute_range = (PetscBool)!same_data;
3343bd2a564bSStefano Zampini         if (nmin >= subset_size) compute_range = PETSC_FALSE;
334408122e43SStefano Zampini 
3345fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
33469036ceccSStefano Zampini           PetscInt nc = 0;
3347d16cbb6bSStefano Zampini 
33489036ceccSStefano Zampini           if (sub_schurs->change_primal_sub) {
33499566063dSJacob Faibussowitsch             PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc));
33509036ceccSStefano Zampini           }
335163a3b9bcSJacob 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));
3352b7ab4a40SStefano Zampini         }
3353b7ab4a40SStefano Zampini 
33549566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
3355b7ab4a40SStefano Zampini         if (compute_range) {
3356d16cbb6bSStefano Zampini 
3357d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
3358bd2a564bSStefano Zampini           if (sub_schurs->is_posdef) {
335908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
33609d54b7f4SStefano 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));
336108122e43SStefano Zampini #else
33629d54b7f4SStefano 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));
336308122e43SStefano Zampini #endif
33649566063dSJacob Faibussowitsch             PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3365bd2a564bSStefano Zampini           } else { /* no theory so far, but it works nicely */
33669036ceccSStefano Zampini             PetscInt  recipe = 0,recipe_m = 1;
3367bd2a564bSStefano Zampini             PetscReal bb[2];
3368bd2a564bSStefano Zampini 
33699566063dSJacob Faibussowitsch             PetscCall(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL));
3370bd2a564bSStefano Zampini             switch (recipe) {
3371bd2a564bSStefano Zampini             case 0:
3372bd2a564bSStefano Zampini               if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; }
3373bd2a564bSStefano Zampini               else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; }
3374bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3375bd2a564bSStefano 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));
3376bd2a564bSStefano Zampini #else
3377bd2a564bSStefano 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));
3378bd2a564bSStefano Zampini #endif
33799566063dSJacob Faibussowitsch               PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3380bd2a564bSStefano Zampini               break;
3381bd2a564bSStefano Zampini             case 1:
3382bd2a564bSStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh;
3383bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3384bd2a564bSStefano 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));
3385bd2a564bSStefano Zampini #else
3386bd2a564bSStefano 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));
3387bd2a564bSStefano Zampini #endif
33889566063dSJacob Faibussowitsch               PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3389bd2a564bSStefano Zampini               if (!scal) {
33909036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
3391bd2a564bSStefano Zampini 
3392aed7e7d0SStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL;
33939566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
33949566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
3395bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3396bd2a564bSStefano 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));
3397bd2a564bSStefano Zampini #else
3398bd2a564bSStefano 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));
3399bd2a564bSStefano Zampini #endif
34009566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3401bd2a564bSStefano Zampini                 B_neigs += B_neigs2;
3402bd2a564bSStefano Zampini               }
3403bd2a564bSStefano Zampini               break;
34049036ceccSStefano Zampini             case 2:
34059036ceccSStefano Zampini               if (scal) {
34069036ceccSStefano Zampini                 bb[0] = PETSC_MIN_REAL;
34079036ceccSStefano Zampini                 bb[1] = 0;
34089036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34099036ceccSStefano 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));
34109036ceccSStefano Zampini #else
34119036ceccSStefano 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));
34129036ceccSStefano Zampini #endif
34139566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34149036ceccSStefano Zampini               } else {
34159036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34169036ceccSStefano Zampini                 PetscBool    import = PETSC_FALSE;
34179036ceccSStefano Zampini 
34189036ceccSStefano Zampini                 lthresh = PetscMax(lthresh,0.0);
34199036ceccSStefano Zampini                 if (lthresh > 0.0) {
34209036ceccSStefano Zampini                   bb[0] = PETSC_MIN_REAL;
34219036ceccSStefano Zampini                   bb[1] = lthresh*lthresh;
34229036ceccSStefano Zampini 
34239036ceccSStefano Zampini                   import = PETSC_TRUE;
34249036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34259036ceccSStefano Zampini                   PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
34269036ceccSStefano Zampini #else
34279036ceccSStefano Zampini                   PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
34289036ceccSStefano Zampini #endif
34299566063dSJacob Faibussowitsch                   PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34309036ceccSStefano Zampini                 }
34319036ceccSStefano Zampini                 bb[0] = PetscMax(lthresh*lthresh,uthresh);
34329036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34339036ceccSStefano Zampini                 if (import) {
34349566063dSJacob Faibussowitsch                   PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
34359566063dSJacob Faibussowitsch                   PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
34369036ceccSStefano Zampini                 }
34379036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34389036ceccSStefano 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));
34399036ceccSStefano Zampini #else
34409036ceccSStefano 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));
34419036ceccSStefano Zampini #endif
34429566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34439036ceccSStefano Zampini                 B_neigs += B_neigs2;
34449036ceccSStefano Zampini               }
34459036ceccSStefano Zampini               break;
34469036ceccSStefano Zampini             case 3:
34479036ceccSStefano Zampini               if (scal) {
34489566063dSJacob Faibussowitsch                 PetscCall(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL));
34499036ceccSStefano Zampini               } else {
34509566063dSJacob Faibussowitsch                 PetscCall(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL));
34519036ceccSStefano Zampini               }
34529036ceccSStefano Zampini               if (!scal) {
34539036ceccSStefano Zampini                 bb[0] = uthresh;
34549036ceccSStefano Zampini                 bb[1] = PETSC_MAX_REAL;
34559036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34569036ceccSStefano 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));
34579036ceccSStefano Zampini #else
34589036ceccSStefano 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));
34599036ceccSStefano Zampini #endif
34609566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34619036ceccSStefano Zampini               }
34629036ceccSStefano Zampini               if (recipe_m > 0 && B_N - B_neigs > 0) {
34639036ceccSStefano Zampini                 PetscBLASInt B_neigs2 = 0;
34649036ceccSStefano Zampini 
34659036ceccSStefano Zampini                 B_IL = 1;
34669566063dSJacob Faibussowitsch                 PetscCall(PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU));
34679566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
34689566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
34699036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX)
34709036ceccSStefano 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));
34719036ceccSStefano Zampini #else
34729036ceccSStefano 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));
34739036ceccSStefano Zampini #endif
34749566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
34759036ceccSStefano Zampini                 B_neigs += B_neigs2;
34769036ceccSStefano Zampini               }
34779036ceccSStefano Zampini               break;
347848cebe81SStefano Zampini             case 4:
347948cebe81SStefano Zampini               bb[0] = PETSC_MIN_REAL; bb[1] = lthresh;
348048cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
348148cebe81SStefano 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));
348248cebe81SStefano Zampini #else
348348cebe81SStefano 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));
348448cebe81SStefano Zampini #endif
34859566063dSJacob Faibussowitsch               PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
348648cebe81SStefano Zampini               {
348748cebe81SStefano Zampini                 PetscBLASInt B_neigs2 = 0;
348848cebe81SStefano Zampini 
348948cebe81SStefano Zampini                 bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL;
34909566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
34919566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
349248cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX)
349348cebe81SStefano 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));
349448cebe81SStefano Zampini #else
349548cebe81SStefano 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));
349648cebe81SStefano Zampini #endif
34979566063dSJacob Faibussowitsch                 PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
349848cebe81SStefano Zampini                 B_neigs += B_neigs2;
349948cebe81SStefano Zampini               }
350048cebe81SStefano Zampini               break;
350180db8efeSStefano Zampini             case 5: /* same as before: first compute all eigenvalues, then filter */
350280db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX)
350380db8efeSStefano 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));
350480db8efeSStefano Zampini #else
350580db8efeSStefano 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));
350680db8efeSStefano Zampini #endif
35079566063dSJacob Faibussowitsch               PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
350880db8efeSStefano Zampini               {
350980db8efeSStefano Zampini                 PetscInt e,k,ne;
351080db8efeSStefano Zampini                 for (e=0,ne=0;e<B_neigs;e++) {
351180db8efeSStefano Zampini                   if (eigs[e] < lthresh || eigs[e] > uthresh) {
351280db8efeSStefano Zampini                     for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k];
351380db8efeSStefano Zampini                     eigs[ne] = eigs[e];
351480db8efeSStefano Zampini                     ne++;
351580db8efeSStefano Zampini                   }
351680db8efeSStefano Zampini                 }
35179566063dSJacob Faibussowitsch                 PetscCall(PetscArraycpy(eigv,S,B_N*ne));
351880db8efeSStefano Zampini                 B_neigs = ne;
351980db8efeSStefano Zampini               }
352080db8efeSStefano Zampini               break;
3521bd2a564bSStefano Zampini             default:
352263a3b9bcSJacob Faibussowitsch               SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %" PetscInt_FMT,recipe);
3523bd2a564bSStefano Zampini             }
3524bd2a564bSStefano Zampini           }
3525bd2a564bSStefano Zampini         } else if (!same_data) { /* this is just to see all the eigenvalues */
3526d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
3527d16cbb6bSStefano Zampini           B_IL = 1;
3528d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
35299d54b7f4SStefano 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));
3530d16cbb6bSStefano Zampini #else
35319d54b7f4SStefano 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));
3532d16cbb6bSStefano Zampini #endif
35339566063dSJacob Faibussowitsch           PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
3534b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
3535b7ab4a40SStefano Zampini           PetscInt k;
353628b400f6SJacob Faibussowitsch           PetscCheck(sub_schurs->change_primal_sub,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
35379566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax));
35389566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(nmax,&B_neigs));
3539b7ab4a40SStefano Zampini           nmin = nmax;
35409566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(eigv,subset_size*nmax));
3541b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
3542b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
3543b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
3544b7ab4a40SStefano Zampini           }
3545d16cbb6bSStefano Zampini         }
35469566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPop());
354708122e43SStefano Zampini         if (B_ierr) {
354863a3b9bcSJacob Faibussowitsch           PetscCheck(B_ierr >= 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT,-B_ierr);
354963a3b9bcSJacob 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);
355063a3b9bcSJacob 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);
355108122e43SStefano Zampini         }
355208122e43SStefano Zampini 
355308122e43SStefano Zampini         if (B_neigs > nmax) {
3554fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
355563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %" PetscBLASInt_FMT " eigs, more than maximum required %" PetscInt_FMT ".\n",B_neigs,nmax));
3556fd14bc51SStefano Zampini           }
3557bd2a564bSStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax;
355808122e43SStefano Zampini           B_neigs = nmax;
355908122e43SStefano Zampini         }
356008122e43SStefano Zampini 
35619552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
35629552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
35639036ceccSStefano Zampini           PetscBLASInt B_neigs2 = 0;
356408122e43SStefano Zampini 
35659d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
3566bd2a564bSStefano Zampini             if (scal) {
3567bd2a564bSStefano Zampini               B_IU = nmin_s;
3568bd2a564bSStefano Zampini               B_IL = B_neigs + 1;
3569bd2a564bSStefano Zampini             } else {
3570f6f667cfSStefano Zampini               B_IL = B_N - nmin_s + 1;
35719d54b7f4SStefano Zampini               B_IU = B_N - B_neigs;
3572bd2a564bSStefano Zampini             }
35739d54b7f4SStefano Zampini           } else {
35749d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
35759d54b7f4SStefano Zampini             B_IU = nmin_s;
35769d54b7f4SStefano Zampini           }
3577fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
357863a3b9bcSJacob 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));
3579fd14bc51SStefano Zampini           }
3580bd2a564bSStefano Zampini           if (sub_schurs->is_symmetric) {
35811ae86dd6SStefano Zampini             PetscInt j,k;
358208122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
35831ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
35841ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
35851ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
358608122e43SStefano Zampini               }
358708122e43SStefano Zampini             }
358808122e43SStefano Zampini           } else {
35899566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size));
35909566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size));
359108122e43SStefano Zampini           }
35929566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
359308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
35949d54b7f4SStefano 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));
359508122e43SStefano Zampini #else
35969d54b7f4SStefano 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));
359708122e43SStefano Zampini #endif
35989566063dSJacob Faibussowitsch           PetscCall(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0));
35999566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
360008122e43SStefano Zampini           B_neigs += B_neigs2;
360108122e43SStefano Zampini         }
360208122e43SStefano Zampini         if (B_ierr) {
360363a3b9bcSJacob Faibussowitsch           PetscCheck(B_ierr >= 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT,-B_ierr);
360463a3b9bcSJacob 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);
360563a3b9bcSJacob 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);
360608122e43SStefano Zampini         }
3607fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
360863a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %" PetscBLASInt_FMT " eigs\n",B_neigs));
360908122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
361008122e43SStefano Zampini             if (eigs[j] == 0.0) {
36119566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n"));
361208122e43SStefano Zampini             } else {
36139d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
361463a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",(double)eigs[j+eigs_start]));
36159d54b7f4SStefano Zampini               } else {
361663a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",(double)(1./eigs[j+eigs_start])));
36179d54b7f4SStefano Zampini               }
3618fd14bc51SStefano Zampini             }
361908122e43SStefano Zampini           }
362008122e43SStefano Zampini         }
3621bd2a564bSStefano Zampini       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented");
3622aff50787SStefano Zampini     }
36236c3e6151SStefano Zampini     /* change the basis back to the original one */
36246c3e6151SStefano Zampini     if (sub_schurs->change) {
362572b8c272SStefano Zampini       Mat change,phi,phit;
36266c3e6151SStefano Zampini 
362703dfb2d7SStefano Zampini       if (pcbddc->dbg_flag > 2) {
36286c3e6151SStefano Zampini         PetscInt ii;
36296c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
363063a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n",ii,B_neigs,B_N));
36316c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3632684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3633684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3634684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
363563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",(double)r,(double)c));
3636684229deSStefano Zampini #else
363763a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",(double)(eigv[(ii+eigs_start)*subset_size+j])));
3638684229deSStefano Zampini #endif
36396c3e6151SStefano Zampini           }
36406c3e6151SStefano Zampini         }
36416c3e6151SStefano Zampini       }
36429566063dSJacob Faibussowitsch       PetscCall(KSPGetOperators(sub_schurs->change[i],&change,NULL));
36439566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit));
36449566063dSJacob Faibussowitsch       PetscCall(MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi));
36459566063dSJacob Faibussowitsch       PetscCall(MatCopy(phi,phit,SAME_NONZERO_PATTERN));
36469566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&phit));
36479566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&phi));
36486c3e6151SStefano Zampini     }
36498bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
36508bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
36519162d606SStefano Zampini     if (B_neigs) {
36529566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size));
3653fd14bc51SStefano Zampini 
3654fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
36559552c7c7SStefano Zampini         PetscInt ii;
36569552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
365763a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n",ii,B_neigs,B_N));
36589552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3659ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3660ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3661ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
366263a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",(double)r,(double)c));
3663ac47001eSStefano Zampini #else
366463a3b9bcSJacob 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]])));
3665ac47001eSStefano Zampini #endif
36669552c7c7SStefano Zampini           }
36679552c7c7SStefano Zampini         }
3668fd14bc51SStefano Zampini       }
36699566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size));
36709162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
36719162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
36729162d606SStefano Zampini       cum++;
367308122e43SStefano Zampini     }
36749566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(sub_schurs->is_subs[i],&idxs));
367508122e43SStefano Zampini     /* shift for next computation */
367608122e43SStefano Zampini     cumarray += subset_size*subset_size;
367708122e43SStefano Zampini   }
3678fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
36799566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
3680fd14bc51SStefano Zampini   }
368108122e43SStefano Zampini 
368208122e43SStefano Zampini   if (mss) {
36839566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray));
36849566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray));
3685f6f667cfSStefano Zampini     /* destroy matrices (junk) */
36869566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_inv_all));
36879566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_tilda_all));
368808122e43SStefano Zampini   }
3689f6f667cfSStefano Zampini   if (allocated_S_St) {
36909566063dSJacob Faibussowitsch     PetscCall(PetscFree2(S,St));
3691f6f667cfSStefano Zampini   }
36929566063dSJacob Faibussowitsch   PetscCall(PetscFree5(eigv,eigs,work,B_iwork,B_ifail));
369308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
36949566063dSJacob Faibussowitsch   PetscCall(PetscFree(rwork));
369508122e43SStefano Zampini #endif
369608122e43SStefano Zampini   if (pcbddc->dbg_flag) {
36971b968477SStefano Zampini     PetscInt maxneigs_r;
36981c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc)));
369963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %" PetscInt_FMT "\n",maxneigs_r));
370008122e43SStefano Zampini   }
37019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0));
370208122e43SStefano Zampini   PetscFunctionReturn(0);
370308122e43SStefano Zampini }
3704b1b3d7a2SStefano Zampini 
3705c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3706c8587f34SStefano Zampini {
37078629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3708c8587f34SStefano Zampini 
3709c8587f34SStefano Zampini   PetscFunctionBegin;
3710f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
37115e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
37129566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalScatters(pc));
3713c8587f34SStefano Zampini 
3714684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
37150fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
37169566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE));
3717c8587f34SStefano Zampini 
37188629588bSStefano Zampini   /*
37198629588bSStefano Zampini      Setup local correction and local part of coarse basis.
37208629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
37218629588bSStefano Zampini   */
37229566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpCorrection(pc,&coarse_submat_vals));
37238629588bSStefano Zampini 
37248629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
37259566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals));
37268629588bSStefano Zampini 
37278629588bSStefano Zampini   /* free */
37289566063dSJacob Faibussowitsch   PetscCall(PetscFree(coarse_submat_vals));
3729c8587f34SStefano Zampini   PetscFunctionReturn(0);
3730c8587f34SStefano Zampini }
3731c8587f34SStefano Zampini 
3732674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3733674ae819SStefano Zampini {
3734674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3735674ae819SStefano Zampini 
3736674ae819SStefano Zampini   PetscFunctionBegin;
37379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
37389566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
37399566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
37409566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
37419566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
37429566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace));
37439566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->onearnullvecs_state));
37449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
37459566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetDofsSplitting(pc,0,NULL));
37469566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetDofsSplittingLocal(pc,0,NULL));
3747674ae819SStefano Zampini   PetscFunctionReturn(0);
3748674ae819SStefano Zampini }
3749674ae819SStefano Zampini 
3750674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3751674ae819SStefano Zampini {
3752674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37534f1b2e48SStefano Zampini   PetscInt       i;
3754674ae819SStefano Zampini 
3755674ae819SStefano Zampini   PetscFunctionBegin;
37569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->nedcG));
37579566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->nedclocal));
37589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->discretegradient));
37599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
37609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix));
37619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->switch_static_change));
37629566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->work_change));
37639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->ConstraintMatrix));
37649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->divudotp));
37659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->divudotp_vl2l));
37669566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphDestroy(&pcbddc->mat_graph));
37674f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
37689566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->local_subs[i]));
37694f1b2e48SStefano Zampini   }
3770e68a0315Sstefano_zampini   pcbddc->n_local_subs = 0;
37719566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->local_subs));
37729566063dSJacob Faibussowitsch   PetscCall(PCBDDCSubSchursDestroy(&pcbddc->sub_schurs));
3773c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
37748af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
37751c7a958bSStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
3776674ae819SStefano Zampini   PetscFunctionReturn(0);
3777674ae819SStefano Zampini }
3778674ae819SStefano Zampini 
3779674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3780674ae819SStefano Zampini {
3781674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3782674ae819SStefano Zampini 
3783674ae819SStefano Zampini   PetscFunctionBegin;
37849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->coarse_vec));
378558da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3786ca92afb2SStefano Zampini     PetscScalar *array;
37879566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B,&array));
37889566063dSJacob Faibussowitsch     PetscCall(PetscFree(array));
378958da7f69SStefano Zampini   }
37909566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->coarse_phi_B));
37919566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->coarse_phi_D));
37929566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->coarse_psi_B));
37939566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->coarse_psi_D));
37949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->vec1_P));
37959566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->vec1_C));
37969566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_auxmat2));
37979566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_auxmat1));
37989566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->vec1_R));
37999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->vec2_R));
38009566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->is_R_local));
38019566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcbddc->R_to_B));
38029566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcbddc->R_to_D));
38039566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob));
38049566063dSJacob Faibussowitsch   PetscCall(KSPReset(pcbddc->ksp_D));
38059566063dSJacob Faibussowitsch   PetscCall(KSPReset(pcbddc->ksp_R));
38069566063dSJacob Faibussowitsch   PetscCall(KSPReset(pcbddc->coarse_ksp));
38079566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_mat));
38089566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->primal_indices_local_idxs));
38099566063dSJacob Faibussowitsch   PetscCall(PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult));
38109566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->global_primal_indices));
38119566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->coarse_subassembling));
38129566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->benign_change));
38139566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->benign_vec));
38149566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc,PETSC_TRUE));
38159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->benign_B0));
38169566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&pcbddc->benign_sf));
3817ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3818ca92afb2SStefano Zampini     PetscInt i;
3819ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
38209566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[i]));
3821ca92afb2SStefano Zampini     }
38229566063dSJacob Faibussowitsch     PetscCall(PetscFree(pcbddc->benign_zerodiag_subs));
3823ca92afb2SStefano Zampini   }
38249566063dSJacob Faibussowitsch   PetscCall(PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0));
3825674ae819SStefano Zampini   PetscFunctionReturn(0);
3826674ae819SStefano Zampini }
3827674ae819SStefano Zampini 
3828f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
38296bfb1811SStefano Zampini {
38306bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
38316bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
38326bfb1811SStefano Zampini   VecType        impVecType;
38334f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
38346bfb1811SStefano Zampini 
38356bfb1811SStefano Zampini   PetscFunctionBegin;
38364f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3837b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
38389566063dSJacob Faibussowitsch   PetscCall(VecGetType(pcis->vec1_N,&impVecType));
3839e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3840e7b262bdSStefano Zampini   /* R nodes */
3841e7b262bdSStefano Zampini   old_size = -1;
3842e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
38439566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcbddc->vec1_R,&old_size));
3844e7b262bdSStefano Zampini   }
3845e7b262bdSStefano Zampini   if (n_R != old_size) {
38469566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->vec1_R));
38479566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->vec2_R));
38489566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R));
38499566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R));
38509566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcbddc->vec1_R,impVecType));
38519566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R));
3852e7b262bdSStefano Zampini   }
3853e7b262bdSStefano Zampini   /* local primal dofs */
3854e7b262bdSStefano Zampini   old_size = -1;
3855e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
38569566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcbddc->vec1_P,&old_size));
3857e7b262bdSStefano Zampini   }
3858e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
38599566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->vec1_P));
38609566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P));
38619566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size));
38629566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcbddc->vec1_P,impVecType));
3863e7b262bdSStefano Zampini   }
3864e7b262bdSStefano Zampini   /* local explicit constraints */
3865e7b262bdSStefano Zampini   old_size = -1;
3866e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
38679566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcbddc->vec1_C,&old_size));
3868e7b262bdSStefano Zampini   }
3869e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
38709566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->vec1_C));
38719566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C));
38729566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints));
38739566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcbddc->vec1_C,impVecType));
387483b7ccabSStefano Zampini   }
38756bfb1811SStefano Zampini   PetscFunctionReturn(0);
38766bfb1811SStefano Zampini }
38776bfb1811SStefano Zampini 
387847f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
387988ebb749SStefano Zampini {
388025084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
388188ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
388288ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3883d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
388425084f0cSStefano Zampini   /* submatrices of local problem */
388580677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
388606656605SStefano Zampini   /* submatrices of local coarse problem */
388706656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
388825084f0cSStefano Zampini   /* working matrices */
388906656605SStefano Zampini   Mat             C_CR;
389025084f0cSStefano Zampini   /* additional working stuff */
389106656605SStefano Zampini   PC              pc_R;
3892c58f9fdbSStefano Zampini   Mat             F,Brhs = NULL;
38935cbda25cSStefano Zampini   Vec             dummy_vec;
38947ebab0bbSStefano Zampini   PetscBool       isLU,isCHOL,need_benign_correction,sparserhs;
389525084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
389606656605SStefano Zampini   PetscScalar     *work;
389706656605SStefano Zampini   PetscInt        *idx_V_B;
3898ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
389906656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
390006656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
390188ebb749SStefano Zampini 
390288ebb749SStefano Zampini   PetscFunctionBegin;
39037827d75bSBarry 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");
39049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0));
3905ffd830a3SStefano Zampini 
3906ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3907b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
39084f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3909b371cd4fSStefano Zampini   n_B = pcis->n_B;
3910b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
391188ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
391288ebb749SStefano Zampini 
391388ebb749SStefano Zampini   /* vertices in boundary numbering */
39149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_vertices,&idx_V_B));
39159566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B));
391663a3b9bcSJacob 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);
391788ebb749SStefano Zampini 
391806656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
39199566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals));
39209566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV));
39219566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(S_VV,pcbddc->local_primal_size));
39229566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV));
39239566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(S_CV,pcbddc->local_primal_size));
39249566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC));
39259566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(S_VC,pcbddc->local_primal_size));
39269566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC));
39279566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(S_CC,pcbddc->local_primal_size));
392806656605SStefano Zampini 
392906656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
39309566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(pcbddc->ksp_R,&pc_R));
39319566063dSJacob Faibussowitsch   PetscCall(PCSetUp(pc_R));
39329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU));
39339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL));
3934ffd830a3SStefano Zampini   lda_rhs = n_R;
3935a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
39367ebab0bbSStefano Zampini   if (isLU || isCHOL) {
39379566063dSJacob Faibussowitsch     PetscCall(PCFactorGetMatrix(pc_R,&F));
3938b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3939df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3940d62866d3SStefano Zampini     MatFactorType      type;
3941d62866d3SStefano Zampini 
3942df4d28bfSStefano Zampini     F = reuse_solver->F;
39439566063dSJacob Faibussowitsch     PetscCall(MatGetFactorType(F,&type));
3944d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
39457ebab0bbSStefano Zampini     if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE;
39469566063dSJacob Faibussowitsch     PetscCall(MatGetSize(F,&lda_rhs,NULL));
394722db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
39487ebab0bbSStefano Zampini   } else F = NULL;
394906656605SStefano Zampini 
3950c58f9fdbSStefano Zampini   /* determine if we can use a sparse right-hand side */
3951c58f9fdbSStefano Zampini   sparserhs = PETSC_FALSE;
3952c58f9fdbSStefano Zampini   if (F) {
3953ea799195SBarry Smith     MatSolverType solver;
3954c58f9fdbSStefano Zampini 
39559566063dSJacob Faibussowitsch     PetscCall(MatFactorGetSolverType(F,&solver));
39569566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs));
3957c58f9fdbSStefano Zampini   }
3958c58f9fdbSStefano Zampini 
3959ffd830a3SStefano Zampini   /* allocate workspace */
3960ffd830a3SStefano Zampini   n = 0;
3961ffd830a3SStefano Zampini   if (n_constraints) {
3962ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3963ffd830a3SStefano Zampini   }
3964ffd830a3SStefano Zampini   if (n_vertices) {
3965ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3966ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3967ffd830a3SStefano Zampini   }
39682a3a6641Sstefano_zampini   if (!pcbddc->symmetric_primal) {
39692a3a6641Sstefano_zampini     n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n);
39702a3a6641Sstefano_zampini   }
39719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n,&work));
3972ffd830a3SStefano Zampini 
39735cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
39745cbda25cSStefano Zampini   dummy_vec = NULL;
39755cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
39769566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&dummy_vec));
39779566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(dummy_vec,lda_rhs,PETSC_DECIDE));
39789566063dSJacob Faibussowitsch     PetscCall(VecSetType(dummy_vec,((PetscObject)pcis->vec1_N)->type_name));
39795cbda25cSStefano Zampini   }
39805cbda25cSStefano Zampini 
39819566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_auxmat1));
39829566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_auxmat2));
39837ebab0bbSStefano Zampini 
398488ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
398588ebb749SStefano Zampini   if (n_constraints) {
3986837cedc9SStefano Zampini     Mat         M3,C_B;
398706656605SStefano Zampini     IS          is_aux;
398806656605SStefano Zampini 
398925084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
39909566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux));
39919566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR));
39929566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B));
399388ebb749SStefano Zampini 
399480677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
399580677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3996c58f9fdbSStefano Zampini     if (!sparserhs) {
39979566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(work,lda_rhs*n_constraints));
399888ebb749SStefano Zampini       for (i=0;i<n_constraints;i++) {
399906656605SStefano Zampini         const PetscScalar *row_cmat_values;
400006656605SStefano Zampini         const PetscInt    *row_cmat_indices;
400106656605SStefano Zampini         PetscInt          size_of_constraint,j;
400288ebb749SStefano Zampini 
40039566063dSJacob Faibussowitsch         PetscCall(MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values));
400406656605SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
4005ffd830a3SStefano Zampini           work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
400606656605SStefano Zampini         }
40079566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values));
400806656605SStefano Zampini       }
40099566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs));
4010c58f9fdbSStefano Zampini     } else {
4011c58f9fdbSStefano Zampini       Mat tC_CR;
4012c58f9fdbSStefano Zampini 
40139566063dSJacob Faibussowitsch       PetscCall(MatScale(C_CR,-1.0));
4014c58f9fdbSStefano Zampini       if (lda_rhs != n_R) {
4015c58f9fdbSStefano Zampini         PetscScalar *aa;
4016c58f9fdbSStefano Zampini         PetscInt    r,*ii,*jj;
4017c58f9fdbSStefano Zampini         PetscBool   done;
4018c58f9fdbSStefano Zampini 
40199566063dSJacob Faibussowitsch         PetscCall(MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done));
402028b400f6SJacob Faibussowitsch         PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
40219566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJGetArray(C_CR,&aa));
40229566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR));
40239566063dSJacob Faibussowitsch         PetscCall(MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done));
402428b400f6SJacob Faibussowitsch         PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4025c58f9fdbSStefano Zampini       } else {
40269566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)C_CR));
4027c58f9fdbSStefano Zampini         tC_CR = C_CR;
4028c58f9fdbSStefano Zampini       }
40299566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(tC_CR,&Brhs));
40309566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&tC_CR));
4031c58f9fdbSStefano Zampini     }
40329566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R));
403306656605SStefano Zampini     if (F) {
4034a3df083aSStefano Zampini       if (need_benign_correction) {
4035df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4036a3df083aSStefano Zampini 
403772b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
40389566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(reuse_solver->benign_save_vals,pcbddc->benign_n));
4039a3df083aSStefano Zampini       }
40409566063dSJacob Faibussowitsch       PetscCall(MatMatSolve(F,Brhs,local_auxmat2_R));
4041a3df083aSStefano Zampini       if (need_benign_correction) {
4042a3df083aSStefano Zampini         PetscScalar        *marr;
4043df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4044a3df083aSStefano Zampini 
40459566063dSJacob Faibussowitsch         PetscCall(MatDenseGetArray(local_auxmat2_R,&marr));
40465cbda25cSStefano Zampini         if (lda_rhs != n_R) {
40475cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
40489566063dSJacob Faibussowitsch             PetscCall(VecPlaceArray(dummy_vec,marr+i*lda_rhs));
40499566063dSJacob Faibussowitsch             PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE));
40509566063dSJacob Faibussowitsch             PetscCall(VecResetArray(dummy_vec));
40515cbda25cSStefano Zampini           }
40525cbda25cSStefano Zampini         } else {
4053a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
40549566063dSJacob Faibussowitsch             PetscCall(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs));
40559566063dSJacob Faibussowitsch             PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE));
40569566063dSJacob Faibussowitsch             PetscCall(VecResetArray(pcbddc->vec1_R));
4057a3df083aSStefano Zampini           }
40585cbda25cSStefano Zampini         }
40599566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreArray(local_auxmat2_R,&marr));
4060a3df083aSStefano Zampini       }
406106656605SStefano Zampini     } else {
406280677318SStefano Zampini       PetscScalar *marr;
406380677318SStefano Zampini 
40649566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(local_auxmat2_R,&marr));
406506656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
40669566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs));
40679566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs));
40689566063dSJacob Faibussowitsch         PetscCall(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R));
40699566063dSJacob Faibussowitsch         PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
40709566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec1_R));
40719566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec2_R));
407206656605SStefano Zampini       }
40739566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(local_auxmat2_R,&marr));
407406656605SStefano Zampini     }
4075c58f9fdbSStefano Zampini     if (sparserhs) {
40769566063dSJacob Faibussowitsch       PetscCall(MatScale(C_CR,-1.0));
4077c58f9fdbSStefano Zampini     }
40789566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Brhs));
407980677318SStefano Zampini     if (!pcbddc->switch_static) {
40809566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2));
408180677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
4082ab2d12f3SJunchao Zhang         Vec r, b;
40839566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVecRead(local_auxmat2_R,i,&r));
40849566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVec(pcbddc->local_auxmat2,i,&b));
40859566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcbddc->R_to_B,r,b,INSERT_VALUES,SCATTER_FORWARD));
40869566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcbddc->R_to_B,r,b,INSERT_VALUES,SCATTER_FORWARD));
40879566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVec(pcbddc->local_auxmat2,i,&b));
40889566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVecRead(local_auxmat2_R,i,&r));
408980677318SStefano Zampini       }
40909566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3));
409180677318SStefano Zampini     } else {
4092ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
4093ffd830a3SStefano Zampini         IS dummy;
4094ffd830a3SStefano Zampini 
40959566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy));
40969566063dSJacob Faibussowitsch         PetscCall(MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2));
40979566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&dummy));
4098ffd830a3SStefano Zampini       } else {
40999566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)local_auxmat2_R));
410080677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
4101ffd830a3SStefano Zampini       }
41029566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3));
410380677318SStefano Zampini     }
41049566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_aux));
410580677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1}  */
41069566063dSJacob Faibussowitsch     PetscCall(MatScale(M3,m_one));
410780677318SStefano Zampini     if (isCHOL) {
41089566063dSJacob Faibussowitsch       PetscCall(MatCholeskyFactor(M3,NULL,NULL));
410980677318SStefano Zampini     } else {
41109566063dSJacob Faibussowitsch       PetscCall(MatLUFactor(M3,NULL,NULL,NULL));
411180677318SStefano Zampini     }
41129566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseInvertFactors_Private(M3));
411380677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
41149566063dSJacob Faibussowitsch     PetscCall(MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1));
41159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C_B));
41169566063dSJacob Faibussowitsch     PetscCall(MatCopy(M3,S_CC,SAME_NONZERO_PATTERN)); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
41179566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&M3));
4118f4ddd8eeSStefano Zampini   }
4119fc227af8SStefano Zampini 
4120fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
412188ebb749SStefano Zampini   if (n_vertices) {
41227ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
41237ebab0bbSStefano Zampini     PetscBool oldpin;
41247ebab0bbSStefano Zampini #endif
41257ebab0bbSStefano Zampini     PetscBool isaij;
412606656605SStefano Zampini     IS        is_aux;
41273a50541eSStefano Zampini 
4128b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
41296816873aSStefano Zampini       IS tis;
41306816873aSStefano Zampini 
41319566063dSJacob Faibussowitsch       PetscCall(ISDuplicate(pcbddc->is_R_local,&tis));
41329566063dSJacob Faibussowitsch       PetscCall(ISSort(tis));
41339566063dSJacob Faibussowitsch       PetscCall(ISComplement(tis,0,pcis->n,&is_aux));
41349566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&tis));
41356816873aSStefano Zampini     } else {
41369566063dSJacob Faibussowitsch       PetscCall(ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux));
41376816873aSStefano Zampini     }
41387ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
4139b470e4b4SRichard Tran Mills     oldpin = pcbddc->local_mat->boundtocpu;
41407ebab0bbSStefano Zampini #endif
41419566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(pcbddc->local_mat,PETSC_TRUE));
41429566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV));
41439566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR));
41449566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isaij));
41457ebab0bbSStefano Zampini     if (!isaij) { /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */
41469566063dSJacob Faibussowitsch       PetscCall(MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR));
41477ebab0bbSStefano Zampini     }
41489566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV));
41497ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
41509566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(pcbddc->local_mat,oldpin));
41517ebab0bbSStefano Zampini #endif
41529566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_aux));
415388ebb749SStefano Zampini   }
415488ebb749SStefano Zampini 
415588ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
4156f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
415706656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
415806656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
41599566063dSJacob Faibussowitsch       PetscCall(MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL));
416006656605SStefano Zampini     }
41619566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal));
416206656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
416306656605SStefano Zampini       PetscScalar *marray;
416406656605SStefano Zampini 
41659566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B,&marray));
41669566063dSJacob Faibussowitsch       PetscCall(PetscFree(marray));
41679566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->coarse_phi_B));
41689566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->coarse_psi_B));
41699566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->coarse_phi_D));
41709566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->coarse_psi_D));
4171f4ddd8eeSStefano Zampini     }
4172f4ddd8eeSStefano Zampini   }
417306656605SStefano Zampini 
4174f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
4175a6e023c1Sstefano_zampini     PetscScalar *marr;
417688ebb749SStefano Zampini 
4177a6e023c1Sstefano_zampini     /* memory size */
417806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
4179a6e023c1Sstefano_zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size;
4180a6e023c1Sstefano_zampini     if (!pcbddc->symmetric_primal) n *= 2;
41819566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n,&marr));
41829566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B));
4183a6e023c1Sstefano_zampini     marr += n_B*pcbddc->local_primal_size;
41848eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
41859566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D));
4186a6e023c1Sstefano_zampini       marr += n_D*pcbddc->local_primal_size;
418788ebb749SStefano Zampini     }
41883301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
41899566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B));
4190a6e023c1Sstefano_zampini       marr += n_B*pcbddc->local_primal_size;
41918eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
41929566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D));
419388ebb749SStefano Zampini       }
419488ebb749SStefano Zampini     } else {
41959566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_B));
4196c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
41971b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
41989566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_D));
4199c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
4200c0553b1fSStefano Zampini       }
420188ebb749SStefano Zampini     }
420206656605SStefano Zampini   }
4203019a44ceSStefano Zampini 
420406656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
42054f1b2e48SStefano Zampini   p0_lidx_I = NULL;
42064f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
4207d12edf2fSStefano Zampini     const PetscInt *idxs;
4208d12edf2fSStefano Zampini 
42099566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(pcis->is_I_local,&idxs));
42109566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcbddc->benign_n,&p0_lidx_I));
42114f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
42129566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]));
42134f1b2e48SStefano Zampini     }
42149566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(pcis->is_I_local,&idxs));
4215d12edf2fSStefano Zampini   }
4216d16cbb6bSStefano Zampini 
421706656605SStefano Zampini   /* vertices */
421806656605SStefano Zampini   if (n_vertices) {
4219c58f9fdbSStefano Zampini     PetscBool restoreavr = PETSC_FALSE;
422016f15bc4SStefano Zampini 
42219566063dSJacob Faibussowitsch     PetscCall(MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV));
422204708bb6SStefano Zampini 
422316f15bc4SStefano Zampini     if (n_R) {
422414393ed6SStefano Zampini       Mat               A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
422506656605SStefano Zampini       PetscBLASInt      B_N,B_one = 1;
42261683a169SBarry Smith       const PetscScalar *x;
42271683a169SBarry Smith       PetscScalar       *y;
422806656605SStefano Zampini 
42299566063dSJacob Faibussowitsch       PetscCall(MatScale(A_RV,m_one));
423014393ed6SStefano Zampini       if (need_benign_correction) {
423114393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
423214393ed6SStefano Zampini         IS                     is_p0;
423314393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
423414393ed6SStefano Zampini 
42359566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(pcbddc->benign_n,&idxs_p0));
42369566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN));
42379566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0));
423863a3b9bcSJacob 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);
42399566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingDestroy(&RtoN));
42409566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0));
42419566063dSJacob Faibussowitsch         PetscCall(MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr));
42429566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&is_p0));
424314393ed6SStefano Zampini       }
424414393ed6SStefano Zampini 
42459566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV));
4246c58f9fdbSStefano Zampini       if (!sparserhs || need_benign_correction) {
4247ffd830a3SStefano Zampini         if (lda_rhs == n_R) {
42489566063dSJacob Faibussowitsch           PetscCall(MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV));
4249ffd830a3SStefano Zampini         } else {
4250ca92afb2SStefano Zampini           PetscScalar    *av,*array;
4251ca92afb2SStefano Zampini           const PetscInt *xadj,*adjncy;
4252ca92afb2SStefano Zampini           PetscInt       n;
4253ca92afb2SStefano Zampini           PetscBool      flg_row;
4254ffd830a3SStefano Zampini 
4255ca92afb2SStefano Zampini           array = work+lda_rhs*n_vertices;
42569566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(array,lda_rhs*n_vertices));
42579566063dSJacob Faibussowitsch           PetscCall(MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV));
42589566063dSJacob Faibussowitsch           PetscCall(MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row));
42599566063dSJacob Faibussowitsch           PetscCall(MatSeqAIJGetArray(A_RV,&av));
4260ca92afb2SStefano Zampini           for (i=0;i<n;i++) {
4261ca92afb2SStefano Zampini             PetscInt j;
4262ca92afb2SStefano Zampini             for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
4263ffd830a3SStefano Zampini           }
42649566063dSJacob Faibussowitsch           PetscCall(MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row));
42659566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&A_RV));
42669566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV));
4267ffd830a3SStefano Zampini         }
4268a3df083aSStefano Zampini         if (need_benign_correction) {
4269df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4270a3df083aSStefano Zampini           PetscScalar        *marr;
4271a3df083aSStefano Zampini 
42729566063dSJacob Faibussowitsch           PetscCall(MatDenseGetArray(A_RV,&marr));
427314393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
427414393ed6SStefano Zampini 
427514393ed6SStefano Zampini                  | 0 0  0 | (V)
427614393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
427714393ed6SStefano Zampini                  | 0 0 -1 | (p0)
427814393ed6SStefano Zampini 
427914393ed6SStefano Zampini           */
4280df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
428114393ed6SStefano Zampini             const PetscScalar *vals;
428214393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
428314393ed6SStefano Zampini             PetscInt          n,j,nz;
428414393ed6SStefano Zampini 
42859566063dSJacob Faibussowitsch             PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz));
42869566063dSJacob Faibussowitsch             PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero));
42879566063dSJacob Faibussowitsch             PetscCall(MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals));
428814393ed6SStefano Zampini             for (j=0;j<n;j++) {
428914393ed6SStefano Zampini               PetscScalar val = vals[j];
429014393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
429114393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
429214393ed6SStefano Zampini             }
42939566063dSJacob Faibussowitsch             PetscCall(MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals));
42949566063dSJacob Faibussowitsch             PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero));
429514393ed6SStefano Zampini           }
42969566063dSJacob Faibussowitsch           PetscCall(MatDenseRestoreArray(A_RV,&marr));
429772b8c272SStefano Zampini         }
42989566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A_RV));
4299c58f9fdbSStefano Zampini         Brhs = A_RV;
4300c58f9fdbSStefano Zampini       } else {
4301c58f9fdbSStefano Zampini         Mat tA_RVT,A_RVT;
4302c58f9fdbSStefano Zampini 
4303c58f9fdbSStefano Zampini         if (!pcbddc->symmetric_primal) {
4304fb6280fbSStefano Zampini           /* A_RV already scaled by -1 */
43059566063dSJacob Faibussowitsch           PetscCall(MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT));
4306c58f9fdbSStefano Zampini         } else {
4307c58f9fdbSStefano Zampini           restoreavr = PETSC_TRUE;
43089566063dSJacob Faibussowitsch           PetscCall(MatScale(A_VR,-1.0));
43099566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)A_VR));
4310c58f9fdbSStefano Zampini           A_RVT = A_VR;
4311c58f9fdbSStefano Zampini         }
4312c58f9fdbSStefano Zampini         if (lda_rhs != n_R) {
4313c58f9fdbSStefano Zampini           PetscScalar *aa;
4314c58f9fdbSStefano Zampini           PetscInt    r,*ii,*jj;
4315c58f9fdbSStefano Zampini           PetscBool   done;
4316c58f9fdbSStefano Zampini 
43179566063dSJacob Faibussowitsch           PetscCall(MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done));
431828b400f6SJacob Faibussowitsch           PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed");
43199566063dSJacob Faibussowitsch           PetscCall(MatSeqAIJGetArray(A_RVT,&aa));
43209566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT));
43219566063dSJacob Faibussowitsch           PetscCall(MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done));
432228b400f6SJacob Faibussowitsch           PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed");
4323c58f9fdbSStefano Zampini         } else {
43249566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)A_RVT));
4325c58f9fdbSStefano Zampini           tA_RVT = A_RVT;
4326c58f9fdbSStefano Zampini         }
43279566063dSJacob Faibussowitsch         PetscCall(MatCreateTranspose(tA_RVT,&Brhs));
43289566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&tA_RVT));
43299566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RVT));
4330c58f9fdbSStefano Zampini       }
433172b8c272SStefano Zampini       if (F) {
433214393ed6SStefano Zampini         /* need to correct the rhs */
433372b8c272SStefano Zampini         if (need_benign_correction) {
433472b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
433572b8c272SStefano Zampini           PetscScalar        *marr;
433672b8c272SStefano Zampini 
43379566063dSJacob Faibussowitsch           PetscCall(MatDenseGetArray(Brhs,&marr));
43385cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43395cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43409566063dSJacob Faibussowitsch               PetscCall(VecPlaceArray(dummy_vec,marr+i*lda_rhs));
43419566063dSJacob Faibussowitsch               PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE));
43429566063dSJacob Faibussowitsch               PetscCall(VecResetArray(dummy_vec));
43435cbda25cSStefano Zampini             }
43445cbda25cSStefano Zampini           } else {
4345a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
43469566063dSJacob Faibussowitsch               PetscCall(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs));
43479566063dSJacob Faibussowitsch               PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE));
43489566063dSJacob Faibussowitsch               PetscCall(VecResetArray(pcbddc->vec1_R));
4349a3df083aSStefano Zampini             }
43505cbda25cSStefano Zampini           }
43519566063dSJacob Faibussowitsch           PetscCall(MatDenseRestoreArray(Brhs,&marr));
4352a3df083aSStefano Zampini         }
43539566063dSJacob Faibussowitsch         PetscCall(MatMatSolve(F,Brhs,A_RRmA_RV));
4354c58f9fdbSStefano Zampini         if (restoreavr) {
43559566063dSJacob Faibussowitsch           PetscCall(MatScale(A_VR,-1.0));
4356c58f9fdbSStefano Zampini         }
435714393ed6SStefano Zampini         /* need to correct the solution */
4358a3df083aSStefano Zampini         if (need_benign_correction) {
4359df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4360a3df083aSStefano Zampini           PetscScalar        *marr;
4361a3df083aSStefano Zampini 
43629566063dSJacob Faibussowitsch           PetscCall(MatDenseGetArray(A_RRmA_RV,&marr));
43635cbda25cSStefano Zampini           if (lda_rhs != n_R) {
43645cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
43659566063dSJacob Faibussowitsch               PetscCall(VecPlaceArray(dummy_vec,marr+i*lda_rhs));
43669566063dSJacob Faibussowitsch               PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE));
43679566063dSJacob Faibussowitsch               PetscCall(VecResetArray(dummy_vec));
43685cbda25cSStefano Zampini             }
43695cbda25cSStefano Zampini           } else {
4370a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
43719566063dSJacob Faibussowitsch               PetscCall(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs));
43729566063dSJacob Faibussowitsch               PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE));
43739566063dSJacob Faibussowitsch               PetscCall(VecResetArray(pcbddc->vec1_R));
4374a3df083aSStefano Zampini             }
43755cbda25cSStefano Zampini           }
43769566063dSJacob Faibussowitsch           PetscCall(MatDenseRestoreArray(A_RRmA_RV,&marr));
4377a3df083aSStefano Zampini         }
437806656605SStefano Zampini       } else {
43799566063dSJacob Faibussowitsch         PetscCall(MatDenseGetArray(Brhs,&y));
438006656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
43819566063dSJacob Faibussowitsch           PetscCall(VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs));
43829566063dSJacob Faibussowitsch           PetscCall(VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs));
43839566063dSJacob Faibussowitsch           PetscCall(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R));
43849566063dSJacob Faibussowitsch           PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
43859566063dSJacob Faibussowitsch           PetscCall(VecResetArray(pcbddc->vec1_R));
43869566063dSJacob Faibussowitsch           PetscCall(VecResetArray(pcbddc->vec2_R));
438706656605SStefano Zampini         }
43889566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreArray(Brhs,&y));
438906656605SStefano Zampini       }
43909566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A_RV));
43919566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Brhs));
4392ffd830a3SStefano Zampini       /* S_VV and S_CV */
439306656605SStefano Zampini       if (n_constraints) {
439406656605SStefano Zampini         Mat B;
439580677318SStefano Zampini 
43969566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(work+lda_rhs*n_vertices,n_B*n_vertices));
439780677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
43989566063dSJacob Faibussowitsch           PetscCall(VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs));
43999566063dSJacob Faibussowitsch           PetscCall(VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B));
44009566063dSJacob Faibussowitsch           PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
44019566063dSJacob Faibussowitsch           PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
44029566063dSJacob Faibussowitsch           PetscCall(VecResetArray(pcis->vec1_B));
44039566063dSJacob Faibussowitsch           PetscCall(VecResetArray(pcbddc->vec1_R));
440480677318SStefano Zampini         }
44059566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B));
44064222ddf1SHong Zhang         /* Reuse dense S_C = pcbddc->local_auxmat1 * B */
44079566063dSJacob Faibussowitsch         PetscCall(MatProductCreateWithMat(pcbddc->local_auxmat1,B,NULL,S_CV));
44089566063dSJacob Faibussowitsch         PetscCall(MatProductSetType(S_CV,MATPRODUCT_AB));
44099566063dSJacob Faibussowitsch         PetscCall(MatProductSetFromOptions(S_CV));
44109566063dSJacob Faibussowitsch         PetscCall(MatProductSymbolic(S_CV));
44119566063dSJacob Faibussowitsch         PetscCall(MatProductNumeric(S_CV));
44129566063dSJacob Faibussowitsch         PetscCall(MatProductClear(S_CV));
44134222ddf1SHong Zhang 
44149566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&B));
44159566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B));
44164222ddf1SHong Zhang         /* Reuse B = local_auxmat2_R * S_CV */
44179566063dSJacob Faibussowitsch         PetscCall(MatProductCreateWithMat(local_auxmat2_R,S_CV,NULL,B));
44189566063dSJacob Faibussowitsch         PetscCall(MatProductSetType(B,MATPRODUCT_AB));
44199566063dSJacob Faibussowitsch         PetscCall(MatProductSetFromOptions(B));
44209566063dSJacob Faibussowitsch         PetscCall(MatProductSymbolic(B));
44219566063dSJacob Faibussowitsch         PetscCall(MatProductNumeric(B));
44224222ddf1SHong Zhang 
44239566063dSJacob Faibussowitsch         PetscCall(MatScale(S_CV,m_one));
44249566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(lda_rhs*n_vertices,&B_N));
4425ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
44269566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&B));
442706656605SStefano Zampini       }
4428ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
44299566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RRmA_RV));
44309566063dSJacob Faibussowitsch         PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV));
44319566063dSJacob Faibussowitsch         PetscCall(MatDenseSetLDA(A_RRmA_RV,lda_rhs));
4432ffd830a3SStefano Zampini       }
44339566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt));
443414393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
443514393ed6SStefano Zampini       if (need_benign_correction) {
4436df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
443714393ed6SStefano Zampini         PetscScalar        *marr,*sums;
443814393ed6SStefano Zampini 
44399566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(n_vertices,&sums));
44409566063dSJacob Faibussowitsch         PetscCall(MatDenseGetArray(S_VVt,&marr));
4441df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
444214393ed6SStefano Zampini           const PetscScalar *vals;
444314393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
444414393ed6SStefano Zampini           PetscInt          n,j,nz;
444514393ed6SStefano Zampini 
44469566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz));
44479566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero));
444814393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
444914393ed6SStefano Zampini             PetscInt k;
445014393ed6SStefano Zampini             sums[j] = 0.;
445114393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
445214393ed6SStefano Zampini           }
44539566063dSJacob Faibussowitsch           PetscCall(MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals));
445414393ed6SStefano Zampini           for (j=0;j<n;j++) {
445514393ed6SStefano Zampini             PetscScalar val = vals[j];
445614393ed6SStefano Zampini             PetscInt k;
445714393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
445814393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
445914393ed6SStefano Zampini             }
446014393ed6SStefano Zampini           }
44619566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals));
44629566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero));
446314393ed6SStefano Zampini         }
44649566063dSJacob Faibussowitsch         PetscCall(PetscFree(sums));
44659566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreArray(S_VVt,&marr));
44669566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RV_bcorr));
446714393ed6SStefano Zampini       }
44689566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A_RRmA_RV));
44699566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(n_vertices*n_vertices,&B_N));
44709566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(A_VV,&x));
44719566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(S_VVt,&y));
447206656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
44739566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(A_VV,&x));
44749566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(S_VVt,&y));
44759566063dSJacob Faibussowitsch       PetscCall(MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN));
44769566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&S_VVt));
4477019a44ceSStefano Zampini     } else {
44789566063dSJacob Faibussowitsch       PetscCall(MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN));
4479d16cbb6bSStefano Zampini     }
44809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_VV));
4481d16cbb6bSStefano Zampini 
448206656605SStefano Zampini     /* coarse basis functions */
448306656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
4484ab2d12f3SJunchao Zhang       Vec         v;
4485ab2d12f3SJunchao Zhang       PetscScalar one = 1.0,zero = 0.0;
448616f15bc4SStefano Zampini 
44879566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i));
44889566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_B,i,&v));
44899566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
44909566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
4491ab2d12f3SJunchao Zhang       if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */
4492ab2d12f3SJunchao Zhang         PetscMPIInt rank;
44939566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_B),&rank));
449408401ef6SPierre Jolivet         PetscCheck(rank <= 1,PetscObjectComm((PetscObject)pcbddc->coarse_phi_B),PETSC_ERR_PLIB,"Expected a sequential dense matrix");
4495ab2d12f3SJunchao Zhang       }
44969566063dSJacob Faibussowitsch       PetscCall(VecSetValues(v,1,&idx_V_B[i],&one,INSERT_VALUES));
44979566063dSJacob Faibussowitsch       PetscCall(VecAssemblyBegin(v)); /* If v is on device, hope VecSetValues() eventually implemented by a host to device memcopy */
44989566063dSJacob Faibussowitsch       PetscCall(VecAssemblyEnd(v));
44999566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B,i,&v));
450006656605SStefano Zampini 
450106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45024f1b2e48SStefano Zampini         PetscInt j;
45034f1b2e48SStefano Zampini 
45049566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_D,i,&v));
45059566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45069566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
4507ab2d12f3SJunchao Zhang         if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */
4508ab2d12f3SJunchao Zhang           PetscMPIInt rank;
45099566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_D),&rank));
451008401ef6SPierre Jolivet           PetscCheck(rank <= 1,PetscObjectComm((PetscObject)pcbddc->coarse_phi_D),PETSC_ERR_PLIB,"Expected a sequential dense matrix");
4511ab2d12f3SJunchao Zhang         }
45129566063dSJacob Faibussowitsch         for (j=0;j<pcbddc->benign_n;j++) PetscCall(VecSetValues(v,1,&p0_lidx_I[j],&zero,INSERT_VALUES));
45139566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(v));
45149566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(v));
45159566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D,i,&v));
451606656605SStefano Zampini       }
45179566063dSJacob Faibussowitsch       PetscCall(VecResetArray(pcbddc->vec1_R));
451806656605SStefano Zampini     }
451904708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
45209566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_RV));
452106656605SStefano Zampini   }
45229566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&dummy_vec));
452306656605SStefano Zampini 
452406656605SStefano Zampini   if (n_constraints) {
452506656605SStefano Zampini     Mat B;
452606656605SStefano Zampini 
45279566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B));
45289566063dSJacob Faibussowitsch     PetscCall(MatScale(S_CC,m_one));
45299566063dSJacob Faibussowitsch     PetscCall(MatProductCreateWithMat(local_auxmat2_R,S_CC,NULL,B));
45309566063dSJacob Faibussowitsch     PetscCall(MatProductSetType(B,MATPRODUCT_AB));
45319566063dSJacob Faibussowitsch     PetscCall(MatProductSetFromOptions(B));
45329566063dSJacob Faibussowitsch     PetscCall(MatProductSymbolic(B));
45339566063dSJacob Faibussowitsch     PetscCall(MatProductNumeric(B));
4534a961b312SStefano Zampini 
45359566063dSJacob Faibussowitsch     PetscCall(MatScale(S_CC,m_one));
453606656605SStefano Zampini     if (n_vertices) {
453703dfb2d7SStefano Zampini       if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
45389566063dSJacob Faibussowitsch         PetscCall(MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC));
453980677318SStefano Zampini       } else {
454080677318SStefano Zampini         Mat S_VCt;
454180677318SStefano Zampini 
4542ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
45439566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&B));
45449566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B));
45459566063dSJacob Faibussowitsch           PetscCall(MatDenseSetLDA(B,lda_rhs));
4546ffd830a3SStefano Zampini         }
45479566063dSJacob Faibussowitsch         PetscCall(MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt));
45489566063dSJacob Faibussowitsch         PetscCall(MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN));
45499566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&S_VCt));
455080677318SStefano Zampini       }
455106656605SStefano Zampini     }
45529566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
455306656605SStefano Zampini     /* coarse basis functions */
455406656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
4555ab2d12f3SJunchao Zhang       Vec v;
455606656605SStefano Zampini 
45579566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i));
45589566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_B,i+n_vertices,&v));
45599566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45609566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45619566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B,i+n_vertices,&v));
456206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
45634f1b2e48SStefano Zampini         PetscInt    j;
4564ab2d12f3SJunchao Zhang         PetscScalar zero = 0.0;
45659566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_D,i+n_vertices,&v));
45669566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45679566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
45689566063dSJacob Faibussowitsch         for (j=0;j<pcbddc->benign_n;j++) PetscCall(VecSetValues(v,1,&p0_lidx_I[j],&zero,INSERT_VALUES));
45699566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(v));
45709566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(v));
45719566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D,i+n_vertices,&v));
457206656605SStefano Zampini       }
45739566063dSJacob Faibussowitsch       PetscCall(VecResetArray(pcbddc->vec1_R));
457406656605SStefano Zampini     }
457506656605SStefano Zampini   }
457680677318SStefano Zampini   if (n_constraints) {
45779566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&local_auxmat2_R));
457880677318SStefano Zampini   }
45799566063dSJacob Faibussowitsch   PetscCall(PetscFree(p0_lidx_I));
458072b8c272SStefano Zampini 
458172b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
458272b8c272SStefano Zampini   if (pcbddc->benign_n) {
458372b8c272SStefano Zampini     Mat               B0_B,B0_BPHI;
458472b8c272SStefano Zampini     IS                is_dummy;
45851683a169SBarry Smith     const PetscScalar *data;
458672b8c272SStefano Zampini     PetscInt          j;
458772b8c272SStefano Zampini 
45889566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy));
45899566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B));
45909566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_dummy));
45919566063dSJacob Faibussowitsch     PetscCall(MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI));
45929566063dSJacob Faibussowitsch     PetscCall(MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI));
45939566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B0_BPHI,&data));
459472b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
459572b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
459672b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
459772b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
459872b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
459972b8c272SStefano Zampini       }
460072b8c272SStefano Zampini     }
46019566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B0_BPHI,&data));
46029566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B0_B));
46039566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B0_BPHI));
460472b8c272SStefano Zampini   }
4605019a44ceSStefano Zampini 
460606656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
46073301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
4608ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
4609ffd830a3SStefano Zampini     PetscScalar *marray;
461006656605SStefano Zampini 
461106656605SStefano Zampini     if (n_constraints) {
4612ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
461306656605SStefano Zampini 
46149566063dSJacob Faibussowitsch       PetscCall(MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT));
46159566063dSJacob Faibussowitsch       PetscCall(MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT));
46169566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C));
46179566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&S_CCT));
461806656605SStefano Zampini       if (n_vertices) {
4619ffd830a3SStefano Zampini         Mat S_VCT;
462006656605SStefano Zampini 
46219566063dSJacob Faibussowitsch         PetscCall(MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT));
46229566063dSJacob Faibussowitsch         PetscCall(MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V));
46239566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&S_VCT));
462406656605SStefano Zampini       }
46259566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C_CRT));
46265b782168SStefano Zampini     } else {
46279566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V));
462806656605SStefano Zampini     }
462916f15bc4SStefano Zampini     if (n_vertices && n_R) {
4630ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
4631ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
4632ffd830a3SStefano Zampini       PetscInt       n;
4633ffd830a3SStefano Zampini       PetscBool      flg_row;
463406656605SStefano Zampini 
4635ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
46369566063dSJacob Faibussowitsch       PetscCall(MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR));
46379566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row));
46389566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(A_VR,&av));
46399566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(B_V,&marray));
4640ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
4641ffd830a3SStefano Zampini         PetscInt j;
4642ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
4643ffd830a3SStefano Zampini       }
46449566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(B_V,&marray));
46459566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row));
46469566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A_VR));
464706656605SStefano Zampini     }
464806656605SStefano Zampini 
4649ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
4650abc8f43dSstefano_zampini     if (n_vertices) {
46519566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(B_V,&marray));
4652ffd830a3SStefano Zampini       for (i=0;i<n_vertices;i++) {
46539566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec1_R,marray+i*n_R));
46549566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec2_R,work+i*n_R));
46559566063dSJacob Faibussowitsch         PetscCall(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R));
46569566063dSJacob Faibussowitsch         PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
46579566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec1_R));
46589566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec2_R));
465906656605SStefano Zampini       }
46609566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(B_V,&marray));
4661abc8f43dSstefano_zampini     }
46625b782168SStefano Zampini     if (B_C) {
46639566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(B_C,&marray));
4664ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
46659566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R));
46669566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec2_R,work+i*n_R));
46679566063dSJacob Faibussowitsch         PetscCall(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R));
46689566063dSJacob Faibussowitsch         PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
46699566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec1_R));
46709566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec2_R));
467106656605SStefano Zampini       }
46729566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(B_C,&marray));
46735b782168SStefano Zampini     }
467406656605SStefano Zampini     /* coarse basis functions */
467506656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4676ab2d12f3SJunchao Zhang       Vec  v;
467706656605SStefano Zampini 
46789566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(pcbddc->vec1_R,work+i*n_R));
46799566063dSJacob Faibussowitsch       PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_B,i,&v));
46809566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
46819566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
468206656605SStefano Zampini       if (i<n_vertices) {
4683ab2d12f3SJunchao Zhang         PetscScalar one = 1.0;
46849566063dSJacob Faibussowitsch         PetscCall(VecSetValues(v,1,&idx_V_B[i],&one,INSERT_VALUES));
46859566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(v));
46869566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(v));
468706656605SStefano Zampini       }
46889566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_B,i,&v));
468906656605SStefano Zampini 
469006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
46919566063dSJacob Faibussowitsch         PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_D,i,&v));
46929566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
46939566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD));
46949566063dSJacob Faibussowitsch         PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_D,i,&v));
469506656605SStefano Zampini       }
46969566063dSJacob Faibussowitsch       PetscCall(VecResetArray(pcbddc->vec1_R));
469706656605SStefano Zampini     }
46989566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_V));
46999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_C));
470006656605SStefano Zampini   }
4701a6e023c1Sstefano_zampini 
4702d62866d3SStefano Zampini   /* free memory */
47039566063dSJacob Faibussowitsch   PetscCall(PetscFree(idx_V_B));
47049566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_VV));
47059566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_CV));
47069566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_VC));
47079566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_CC));
47089566063dSJacob Faibussowitsch   PetscCall(PetscFree(work));
4709d62866d3SStefano Zampini   if (n_vertices) {
47109566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_VR));
4711d62866d3SStefano Zampini   }
4712d62866d3SStefano Zampini   if (n_constraints) {
47139566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C_CR));
4714d62866d3SStefano Zampini   }
47159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0));
47168ead10e4SStefano Zampini 
471788ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
471888ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
471988ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4720d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
472188ebb749SStefano Zampini     Mat         coarse_sub_mat;
472225084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
472388ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
472488ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
472588ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
47268bec7fa6SStefano Zampini     Mat         C_B,CPHI;
47278bec7fa6SStefano Zampini     IS          is_dummy;
47288bec7fa6SStefano Zampini     Vec         mones;
472988ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
473088ebb749SStefano Zampini     PetscReal   real_value;
473188ebb749SStefano Zampini 
4732a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4733a3df083aSStefano Zampini       Mat A;
47349566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignProject(pc,NULL,NULL,&A));
47359566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II));
47369566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB));
47379566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI));
47389566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB));
47399566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A));
4740a3df083aSStefano Zampini     } else {
47419566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II));
47429566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB));
47439566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI));
47449566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB));
4745a3df083aSStefano Zampini     }
47469566063dSJacob Faibussowitsch     PetscCall(MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D));
47479566063dSJacob Faibussowitsch     PetscCall(MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B));
4748ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
47499566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D));
47509566063dSJacob Faibussowitsch       PetscCall(MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B));
475188ebb749SStefano Zampini     }
47529566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat));
475388ebb749SStefano Zampini 
47549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
47559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal));
47569566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
4757ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
47589566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47599566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1));
47609566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
47619566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47629566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2));
47639566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
47649566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47659566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3));
47669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
47679566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47689566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4));
47699566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
477088ebb749SStefano Zampini     } else {
47719566063dSJacob Faibussowitsch       PetscCall(MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1));
47729566063dSJacob Faibussowitsch       PetscCall(MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2));
47739566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47749566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3));
47759566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
47769566063dSJacob Faibussowitsch       PetscCall(MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT));
47779566063dSJacob Faibussowitsch       PetscCall(MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4));
47789566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&AUXMAT));
477988ebb749SStefano Zampini     }
47809566063dSJacob Faibussowitsch     PetscCall(MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN));
47819566063dSJacob Faibussowitsch     PetscCall(MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN));
47829566063dSJacob Faibussowitsch     PetscCall(MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN));
47839566063dSJacob Faibussowitsch     PetscCall(MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1));
47844f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4785fc227af8SStefano Zampini       Mat               B0_B,B0_BPHI;
47861683a169SBarry Smith       const PetscScalar *data2;
47871683a169SBarry Smith       PetscScalar       *data;
47884f1b2e48SStefano Zampini       PetscInt          j;
4789d12edf2fSStefano Zampini 
47909566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy));
47919566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B));
47929566063dSJacob Faibussowitsch       PetscCall(MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI));
47939566063dSJacob Faibussowitsch       PetscCall(MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI));
47949566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(TM1,&data));
47959566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B0_BPHI,&data2));
47964f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
47974f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4798d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
47994f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
48004f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
48014f1b2e48SStefano Zampini         }
4802d12edf2fSStefano Zampini       }
48039566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(TM1,&data));
48049566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B0_BPHI,&data2));
48059566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B0_B));
48069566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is_dummy));
48079566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B0_BPHI));
4808d12edf2fSStefano Zampini     }
4809d12edf2fSStefano Zampini #if 0
4810d12edf2fSStefano Zampini   {
4811d12edf2fSStefano Zampini     PetscViewer viewer;
4812d12edf2fSStefano Zampini     char filename[256];
4813ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
48149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer));
48159566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB));
48169566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coarse_sub_mat,"computed"));
48179566063dSJacob Faibussowitsch     PetscCall(MatView(coarse_sub_mat,viewer));
48189566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)TM1,"projected"));
48199566063dSJacob Faibussowitsch     PetscCall(MatView(TM1,viewer));
4820a7414863SStefano Zampini     if (pcbddc->coarse_phi_B) {
48219566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B"));
48229566063dSJacob Faibussowitsch       PetscCall(MatView(pcbddc->coarse_phi_B,viewer));
482372b8c272SStefano Zampini     }
4824ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
48259566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D"));
48269566063dSJacob Faibussowitsch       PetscCall(MatView(pcbddc->coarse_phi_D,viewer));
4827ffd830a3SStefano Zampini     }
4828ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
48299566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B"));
48309566063dSJacob Faibussowitsch       PetscCall(MatView(pcbddc->coarse_psi_B,viewer));
4831ffd830a3SStefano Zampini     }
483272b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
48339566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D"));
48349566063dSJacob Faibussowitsch       PetscCall(MatView(pcbddc->coarse_psi_D,viewer));
4835ffd830a3SStefano Zampini     }
48369566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcbddc->local_mat,"A"));
48379566063dSJacob Faibussowitsch     PetscCall(MatView(pcbddc->local_mat,viewer));
48389566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C"));
48399566063dSJacob Faibussowitsch     PetscCall(MatView(pcbddc->ConstraintMatrix,viewer));
48409566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcis->is_I_local,"I"));
48419566063dSJacob Faibussowitsch     PetscCall(ISView(pcis->is_I_local,viewer));
48429566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcis->is_B_local,"B"));
48439566063dSJacob Faibussowitsch     PetscCall(ISView(pcis->is_B_local,viewer));
48449566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R"));
48459566063dSJacob Faibussowitsch     PetscCall(ISView(pcbddc->is_R_local,viewer));
48469566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
4847d12edf2fSStefano Zampini   }
4848d12edf2fSStefano Zampini #endif
48499566063dSJacob Faibussowitsch     PetscCall(MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN));
48509566063dSJacob Faibussowitsch     PetscCall(MatNorm(TM1,NORM_FROBENIUS,&real_value));
48519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
485263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,(double)real_value));
48538bec7fa6SStefano Zampini 
48548bec7fa6SStefano Zampini     /* check constraints */
48559566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy));
48569566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B));
48574f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
48589566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI));
4859a00504b5SStefano Zampini     } else {
4860a00504b5SStefano Zampini       PetscScalar *data;
4861a00504b5SStefano Zampini       Mat         tmat;
48629566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B,&data));
48639566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat));
48649566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(pcbddc->coarse_phi_B,&data));
48659566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI));
48669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&tmat));
4867a00504b5SStefano Zampini     }
48689566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(CPHI,&mones,NULL));
48699566063dSJacob Faibussowitsch     PetscCall(VecSet(mones,-1.0));
48709566063dSJacob Faibussowitsch     PetscCall(MatDiagonalSet(CPHI,mones,ADD_VALUES));
48719566063dSJacob Faibussowitsch     PetscCall(MatNorm(CPHI,NORM_FROBENIUS,&real_value));
487263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,(double)real_value));
4873ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
48749566063dSJacob Faibussowitsch       PetscCall(MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI));
48759566063dSJacob Faibussowitsch       PetscCall(VecSet(mones,-1.0));
48769566063dSJacob Faibussowitsch       PetscCall(MatDiagonalSet(CPHI,mones,ADD_VALUES));
48779566063dSJacob Faibussowitsch       PetscCall(MatNorm(CPHI,NORM_FROBENIUS,&real_value));
487863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,(double)real_value));
487988ebb749SStefano Zampini     }
48809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&C_B));
48819566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&CPHI));
48829566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_dummy));
48839566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&mones));
48849566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
48859566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_II));
48869566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_BB));
48879566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_IB));
48889566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A_BI));
48899566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&TM1));
48909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&TM2));
48919566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&TM3));
48929566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&TM4));
48939566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&coarse_phi_D));
48949566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&coarse_phi_B));
4895ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
48969566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&coarse_psi_D));
48979566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&coarse_psi_B));
489888ebb749SStefano Zampini     }
48999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&coarse_sub_mat));
490088ebb749SStefano Zampini   }
49017ebab0bbSStefano Zampini   /* FINAL CUDA support (we cannot currently mix viennacl and cuda vectors */
49027ebab0bbSStefano Zampini   {
49037ebab0bbSStefano Zampini     PetscBool gpu;
49047ebab0bbSStefano Zampini 
49059566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pcis->vec1_N,VECSEQCUDA,&gpu));
49067ebab0bbSStefano Zampini     if (gpu) {
49077ebab0bbSStefano Zampini       if (pcbddc->local_auxmat1) {
49089566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->local_auxmat1,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat1));
49097ebab0bbSStefano Zampini       }
49107ebab0bbSStefano Zampini       if (pcbddc->local_auxmat2) {
49119566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->local_auxmat2,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat2));
49127ebab0bbSStefano Zampini       }
49137ebab0bbSStefano Zampini       if (pcbddc->coarse_phi_B) {
49149566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->coarse_phi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_B));
49157ebab0bbSStefano Zampini       }
49167ebab0bbSStefano Zampini       if (pcbddc->coarse_phi_D) {
49179566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->coarse_phi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_D));
49187ebab0bbSStefano Zampini       }
49197ebab0bbSStefano Zampini       if (pcbddc->coarse_psi_B) {
49209566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->coarse_psi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_B));
49217ebab0bbSStefano Zampini       }
49227ebab0bbSStefano Zampini       if (pcbddc->coarse_psi_D) {
49239566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->coarse_psi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_D));
49247ebab0bbSStefano Zampini       }
49257ebab0bbSStefano Zampini     }
49267ebab0bbSStefano Zampini   }
49278629588bSStefano Zampini   /* get back data */
49288629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
492988ebb749SStefano Zampini   PetscFunctionReturn(0);
493088ebb749SStefano Zampini }
493188ebb749SStefano Zampini 
49327dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4933aa0d41d4SStefano Zampini {
4934d65f70fdSStefano Zampini   Mat            *work_mat;
4935d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4936d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4937c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4938aa0d41d4SStefano Zampini 
4939aa0d41d4SStefano Zampini   PetscFunctionBegin;
49409566063dSJacob Faibussowitsch   PetscCall(ISSorted(isrow,&rsorted));
49419566063dSJacob Faibussowitsch   PetscCall(ISSorted(iscol,&csorted));
49429566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow,&rsize));
49439566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol,&csize));
4944aa0d41d4SStefano Zampini 
4945d65f70fdSStefano Zampini   if (!rsorted) {
4946906d46d4SStefano Zampini     const PetscInt *idxs;
4947906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4948aa0d41d4SStefano Zampini 
49499566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(rsize,&idxs_perm_r));
49509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(rsize,&idxs_sorted));
4951d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4952d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4953aa0d41d4SStefano Zampini     }
49549566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(isrow,&idxs));
49559566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r));
4956d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4957d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4958aa0d41d4SStefano Zampini     }
49599566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(isrow,&idxs));
49609566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s));
4961d65f70fdSStefano Zampini   } else {
49629566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)isrow));
4963d65f70fdSStefano Zampini     isrow_s = isrow;
4964aa0d41d4SStefano Zampini   }
4965906d46d4SStefano Zampini 
4966d65f70fdSStefano Zampini   if (!csorted) {
4967d65f70fdSStefano Zampini     if (isrow == iscol) {
49689566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)isrow_s));
4969d65f70fdSStefano Zampini       iscol_s = isrow_s;
4970d65f70fdSStefano Zampini     } else {
4971d65f70fdSStefano Zampini       const PetscInt *idxs;
4972d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4973906d46d4SStefano Zampini 
49749566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(csize,&idxs_perm_c));
49759566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(csize,&idxs_sorted));
4976d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4977d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4978d65f70fdSStefano Zampini       }
49799566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(iscol,&idxs));
49809566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithPermutation(csize,idxs,idxs_perm_c));
4981d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4982d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4983d65f70fdSStefano Zampini       }
49849566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(iscol,&idxs));
49859566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s));
4986d65f70fdSStefano Zampini     }
4987d65f70fdSStefano Zampini   } else {
49889566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)iscol));
4989d65f70fdSStefano Zampini     iscol_s = iscol;
4990d65f70fdSStefano Zampini   }
4991d65f70fdSStefano Zampini 
49929566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat));
4993d65f70fdSStefano Zampini 
4994d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4995906d46d4SStefano Zampini     Mat      new_mat;
4996d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4997906d46d4SStefano Zampini 
4998d65f70fdSStefano Zampini     if (!rsorted) {
4999d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
50009566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(rsize,&idxs_r));
5001d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
5002d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
5003906d46d4SStefano Zampini       }
50049566063dSJacob Faibussowitsch       PetscCall(PetscFree(idxs_perm_r));
50059566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r));
5006d65f70fdSStefano Zampini     } else {
50079566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r));
5008906d46d4SStefano Zampini     }
50099566063dSJacob Faibussowitsch     PetscCall(ISSetPermutation(is_perm_r));
5010d65f70fdSStefano Zampini 
5011d65f70fdSStefano Zampini     if (!csorted) {
5012d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
50139566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)is_perm_r));
5014d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
5015d65f70fdSStefano Zampini       } else {
5016d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
501728b400f6SJacob Faibussowitsch         PetscCheck(idxs_perm_c,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
50189566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(csize,&idxs_c));
5019d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
5020d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
5021d65f70fdSStefano Zampini         }
50229566063dSJacob Faibussowitsch         PetscCall(PetscFree(idxs_perm_c));
50239566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c));
5024d65f70fdSStefano Zampini       }
5025d65f70fdSStefano Zampini     } else {
50269566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c));
5027d65f70fdSStefano Zampini     }
50289566063dSJacob Faibussowitsch     PetscCall(ISSetPermutation(is_perm_c));
5029d65f70fdSStefano Zampini 
50309566063dSJacob Faibussowitsch     PetscCall(MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat));
50319566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&work_mat[0]));
5032d65f70fdSStefano Zampini     work_mat[0] = new_mat;
50339566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_perm_r));
50349566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is_perm_c));
5035d65f70fdSStefano Zampini   }
5036d65f70fdSStefano Zampini 
50379566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)work_mat[0]));
5038d65f70fdSStefano Zampini   *B = work_mat[0];
50399566063dSJacob Faibussowitsch   PetscCall(MatDestroyMatrices(1,&work_mat));
50409566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&isrow_s));
50419566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&iscol_s));
5042d65f70fdSStefano Zampini   PetscFunctionReturn(0);
5043d65f70fdSStefano Zampini }
5044d65f70fdSStefano Zampini 
50455e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
5046aa0d41d4SStefano Zampini {
5047aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
50485e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5049022d8d2bSstefano_zampini   Mat            new_mat,lA;
50505e8657edSStefano Zampini   IS             is_local,is_global;
5051d65f70fdSStefano Zampini   PetscInt       local_size;
5052d65f70fdSStefano Zampini   PetscBool      isseqaij;
5053aa0d41d4SStefano Zampini 
5054aa0d41d4SStefano Zampini   PetscFunctionBegin;
50559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->local_mat));
50569566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,&local_size,NULL));
50579566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local));
50589566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping,is_local,&is_global));
50599566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_local));
50609566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat));
50619566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_global));
5062906d46d4SStefano Zampini 
5063906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
5064906d46d4SStefano Zampini     Vec       x,x_change;
5065906d46d4SStefano Zampini     PetscReal error;
5066906d46d4SStefano Zampini 
50679566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change));
50689566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(x,NULL));
50699566063dSJacob Faibussowitsch     PetscCall(MatMult(ChangeOfBasisMatrix,x,x_change));
50709566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD));
50719566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD));
50729566063dSJacob Faibussowitsch     PetscCall(MatMult(new_mat,matis->x,matis->y));
507388428137SStefano Zampini     if (!pcbddc->change_interior) {
507488428137SStefano Zampini       const PetscScalar *x,*y,*v;
507588428137SStefano Zampini       PetscReal         lerror = 0.;
507688428137SStefano Zampini       PetscInt          i;
507788428137SStefano Zampini 
50789566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(matis->x,&x));
50799566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(matis->y,&y));
50809566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(matis->counter,&v));
508188428137SStefano Zampini       for (i=0;i<local_size;i++)
508288428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
508388428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
50849566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(matis->x,&x));
50859566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(matis->y,&y));
50869566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(matis->counter,&v));
50871c2dc1cbSBarry Smith       PetscCall(MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)pc)));
5088637e8532SStefano Zampini       if (error > PETSC_SMALL) {
5089637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
509063a3b9bcSJacob Faibussowitsch           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e",(double)error);
5091637e8532SStefano Zampini         } else {
509263a3b9bcSJacob Faibussowitsch           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e",(double)error);
5093637e8532SStefano Zampini         }
5094637e8532SStefano Zampini       }
509588428137SStefano Zampini     }
50969566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE));
50979566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE));
50989566063dSJacob Faibussowitsch     PetscCall(VecAXPY(x,-1.0,x_change));
50999566063dSJacob Faibussowitsch     PetscCall(VecNorm(x,NORM_INFINITY,&error));
5100637e8532SStefano Zampini     if (error > PETSC_SMALL) {
5101637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
510263a3b9bcSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",(double)error);
5103637e8532SStefano Zampini       } else {
510463a3b9bcSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e",(double)error);
5105637e8532SStefano Zampini       }
5106637e8532SStefano Zampini     }
51079566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&x));
51089566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&x_change));
5109906d46d4SStefano Zampini   }
5110906d46d4SStefano Zampini 
5111022d8d2bSstefano_zampini   /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */
51129566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA));
5113022d8d2bSstefano_zampini 
511422d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
51159566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij));
511622d5777bSStefano Zampini   if (isseqaij) {
51179566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
51189566063dSJacob Faibussowitsch     PetscCall(MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat));
5119022d8d2bSstefano_zampini     if (lA) {
5120022d8d2bSstefano_zampini       Mat work;
51219566063dSJacob Faibussowitsch       PetscCall(MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work));
51229566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work));
51239566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&work));
5124022d8d2bSstefano_zampini     }
5125aa0d41d4SStefano Zampini   } else {
5126a00504b5SStefano Zampini     Mat work_mat;
51271cf9b237SStefano Zampini 
51289566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
51299566063dSJacob Faibussowitsch     PetscCall(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat));
51309566063dSJacob Faibussowitsch     PetscCall(MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat));
51319566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&work_mat));
5132022d8d2bSstefano_zampini     if (lA) {
5133022d8d2bSstefano_zampini       Mat work;
51349566063dSJacob Faibussowitsch       PetscCall(MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat));
51359566063dSJacob Faibussowitsch       PetscCall(MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work));
51369566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work));
51379566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&work));
5138022d8d2bSstefano_zampini     }
5139aa0d41d4SStefano Zampini   }
51403301b35fSStefano Zampini   if (matis->A->symmetric_set) {
51419566063dSJacob Faibussowitsch     PetscCall(MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric));
5142e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
51439566063dSJacob Faibussowitsch     PetscCall(MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric));
5144e496cd5dSStefano Zampini #endif
51453301b35fSStefano Zampini   }
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;
541692cccca0SStefano Zampini   PetscBool      issbaij,opts;
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     }
54743301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
54759566063dSJacob Faibussowitsch       PetscCall(MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric));
5476964fefecSStefano Zampini     }
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 */
549992cccca0SStefano Zampini     if (opts) {
55009566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(pcbddc->ksp_D));
550192cccca0SStefano Zampini     }
55029566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pcis->pA_II,&nnsp));
55036d9e27e4SStefano Zampini     if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */
55049566063dSJacob Faibussowitsch       PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcis->is_I_local,pcis->pA_II));
550592cccca0SStefano Zampini     }
55069566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pcis->pA_II,&nnsp));
55079566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcbddc->ksp_D,&pc_temp));
55089566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f));
550992cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5510cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5511cd18cfedSStefano Zampini       const PetscInt *idxs;
5512cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5513cd18cfedSStefano Zampini 
55149566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcis->is_I_local,&nl));
55159566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcis->is_I_local,&idxs));
55169566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl*cdim,&scoords));
5517cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5518cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5519cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5520cd18cfedSStefano Zampini         }
5521cd18cfedSStefano Zampini       }
55229566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcis->is_I_local,&idxs));
55239566063dSJacob Faibussowitsch       PetscCall(PCSetCoordinates(pc_temp,cdim,nl,scoords));
55249566063dSJacob Faibussowitsch       PetscCall(PetscFree(scoords));
5525cd18cfedSStefano Zampini     }
5526b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
5527df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5528d62866d3SStefano Zampini 
55299566063dSJacob Faibussowitsch       PetscCall(KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver));
5530d5574798SStefano Zampini     }
553192cccca0SStefano Zampini 
5532304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5533304d26faSStefano Zampini     if (!n_D) {
55349566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->ksp_D,&pc_temp));
55359566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,PCNONE));
5536304d26faSStefano Zampini     }
55379566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcbddc->ksp_D));
5538304d26faSStefano Zampini     /* set ksp_D into pcis data */
55399566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->ksp_D));
55409566063dSJacob Faibussowitsch     PetscCall(KSPDestroy(&pcis->ksp_D));
5541304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
5542684f6988SStefano Zampini   }
5543304d26faSStefano Zampini 
5544304d26faSStefano Zampini   /* NEUMANN PROBLEM */
55450a545947SLisandro Dalcin   A_RR = NULL;
5546684f6988SStefano Zampini   if (neumann) {
5547d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
554804708bb6SStefano Zampini     PetscInt        ibs,mbs;
55490aa714b2SStefano Zampini     PetscBool       issbaij, reuse_neumann_solver;
555004708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
55510aa714b2SStefano Zampini 
55520aa714b2SStefano Zampini     reuse_neumann_solver = PETSC_FALSE;
55530aa714b2SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
55540aa714b2SStefano Zampini       IS iP;
55550aa714b2SStefano Zampini 
55560aa714b2SStefano Zampini       reuse_neumann_solver = PETSC_TRUE;
55579566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP));
55580aa714b2SStefano Zampini       if (iP) reuse_neumann_solver = PETSC_FALSE;
55590aa714b2SStefano Zampini     }
5560f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
55619566063dSJacob Faibussowitsch     PetscCall(ISGetSize(pcbddc->is_R_local,&n_R));
5562f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
5563f4ddd8eeSStefano Zampini       PetscInt nn_R;
55649566063dSJacob Faibussowitsch       PetscCall(KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR));
55659566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A_RR));
55669566063dSJacob Faibussowitsch       PetscCall(MatGetSize(A_RR,&nn_R,NULL));
5567f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
55689566063dSJacob Faibussowitsch         PetscCall(KSPReset(pcbddc->ksp_R));
55699566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RR));
5570f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5571f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
5572727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
55739566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&A_RR));
5574f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
5575f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
5576f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
5577f4ddd8eeSStefano Zampini         }
5578f4ddd8eeSStefano Zampini       }
5579f4ddd8eeSStefano Zampini       /* last check */
5580d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
55819566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RR));
5582f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
5583f4ddd8eeSStefano Zampini       }
5584f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
5585f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
5586f4ddd8eeSStefano Zampini     }
5587365a3a41SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection
5588365a3a41SStefano Zampini        TODO: Get Rid of these conversions */
55899566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pcbddc->local_mat,&mbs));
55909566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(pcbddc->is_R_local,&ibs));
55919566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij));
559204708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
559304708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
55949566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&pcbddc->local_mat));
55959566063dSJacob Faibussowitsch         PetscCall(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat));
5596af732b37SStefano Zampini       } else {
55979566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat));
55986816873aSStefano Zampini       }
559904708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
560004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
56019566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&pcbddc->local_mat));
56029566063dSJacob Faibussowitsch         PetscCall(MatConvert(matis->A,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat));
560304708bb6SStefano Zampini       } else {
56049566063dSJacob Faibussowitsch         PetscCall(MatConvert(pcbddc->local_mat,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat));
560504708bb6SStefano Zampini       }
560604708bb6SStefano Zampini     }
5607a00504b5SStefano Zampini     /* extract A_RR */
56080aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5609a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5610a00504b5SStefano Zampini 
5611a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
56129566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RR));
5613a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
56149566063dSJacob Faibussowitsch           PetscCall(PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR));
561516e386b8SStefano Zampini         } else {
56169566063dSJacob Faibussowitsch           PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR));
5617a00504b5SStefano Zampini         }
5618a00504b5SStefano Zampini       } else {
56199566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&A_RR));
56209566063dSJacob Faibussowitsch         PetscCall(PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL));
56219566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A_RR));
5622a00504b5SStefano Zampini       }
5623a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
56249566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR));
562516e386b8SStefano Zampini     }
56263301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
56279566063dSJacob Faibussowitsch       PetscCall(MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric));
56286816873aSStefano Zampini     }
562992cccca0SStefano Zampini     opts = PETSC_FALSE;
5630f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
563192cccca0SStefano Zampini       opts = PETSC_TRUE;
56329566063dSJacob Faibussowitsch       PetscCall(KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R));
56339566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1));
5634304d26faSStefano Zampini       /* default */
56359566063dSJacob Faibussowitsch       PetscCall(KSPSetType(pcbddc->ksp_R,KSPPREONLY));
56369566063dSJacob Faibussowitsch       PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix));
56379566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->ksp_R,&pc_temp));
56389566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij));
56399577ea80SStefano Zampini       if (issbaij) {
56409566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc_temp,PCCHOLESKY));
56419577ea80SStefano Zampini       } else {
56429566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc_temp,PCLU));
56439577ea80SStefano Zampini       }
56449566063dSJacob Faibussowitsch       PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_R,pc->erroriffailure));
564592cccca0SStefano Zampini     }
56469566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR));
56479566063dSJacob Faibussowitsch     PetscCall(MatSetOptionsPrefix(A_RR,((PetscObject)pcbddc->ksp_R)->prefix));
564892cccca0SStefano Zampini     if (opts) { /* Allow user's customization once */
56499566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(pcbddc->ksp_R));
565092cccca0SStefano Zampini     }
56519566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(A_RR,&nnsp));
56526d9e27e4SStefano Zampini     if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */
56539566063dSJacob Faibussowitsch       PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcbddc->is_R_local,A_RR));
565492cccca0SStefano Zampini     }
56559566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(A_RR,&nnsp));
56569566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcbddc->ksp_R,&pc_temp));
56579566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f));
565892cccca0SStefano Zampini     if (f && pcbddc->mat_graph->cloc && !nnsp) {
5659cd18cfedSStefano Zampini       PetscReal      *coords = pcbddc->mat_graph->coords,*scoords;
5660cd18cfedSStefano Zampini       const PetscInt *idxs;
5661cd18cfedSStefano Zampini       PetscInt       cdim = pcbddc->mat_graph->cdim,nl,i,d;
5662cd18cfedSStefano Zampini 
56639566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->is_R_local,&nl));
56649566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->is_R_local,&idxs));
56659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl*cdim,&scoords));
5666cd18cfedSStefano Zampini       for (i=0;i<nl;i++) {
5667cd18cfedSStefano Zampini         for (d=0;d<cdim;d++) {
5668cd18cfedSStefano Zampini           scoords[i*cdim+d] = coords[idxs[i]*cdim+d];
5669cd18cfedSStefano Zampini         }
5670cd18cfedSStefano Zampini       }
56719566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->is_R_local,&idxs));
56729566063dSJacob Faibussowitsch       PetscCall(PCSetCoordinates(pc_temp,cdim,nl,scoords));
56739566063dSJacob Faibussowitsch       PetscCall(PetscFree(scoords));
5674cd18cfedSStefano Zampini     }
567592cccca0SStefano Zampini 
5676304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
5677304d26faSStefano Zampini     if (!n_R) {
56789566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->ksp_R,&pc_temp));
56799566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,PCNONE));
5680304d26faSStefano Zampini     }
5681df4d28bfSStefano Zampini     /* Reuse solver if it is present */
56820aa714b2SStefano Zampini     if (reuse_neumann_solver) {
5683df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5684d62866d3SStefano Zampini 
56859566063dSJacob Faibussowitsch       PetscCall(KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver));
5686d62866d3SStefano Zampini     }
56879566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcbddc->ksp_R));
5688684f6988SStefano Zampini   }
5689304d26faSStefano Zampini 
5690684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
56919566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
56929566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
56939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
5694684f6988SStefano Zampini   }
56959566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0));
5696c7017625SStefano Zampini 
5697c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
5698c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
56999566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE));
5700c7017625SStefano Zampini   }
5701c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
57029566063dSJacob Faibussowitsch     PetscCall(PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]));
5703c7017625SStefano Zampini   }
5704c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
57059566063dSJacob Faibussowitsch     PetscCall(PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]));
5706c7017625SStefano Zampini   }
5707c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
5708c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
5709684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
57109566063dSJacob Faibussowitsch       PetscCall(VecSetRandom(pcis->vec1_D,NULL));
57119566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D));
57129566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D));
57139566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
57149566063dSJacob Faibussowitsch       PetscCall(VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D));
57159566063dSJacob Faibussowitsch       PetscCall(VecNorm(pcis->vec1_D,NORM_INFINITY,&value));
571663a3b9bcSJacob 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));
57179566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
5718304d26faSStefano Zampini     }
5719684f6988SStefano Zampini     if (neumann) { /* Neumann */
57209566063dSJacob Faibussowitsch       PetscCall(VecSetRandom(pcbddc->vec1_R,NULL));
57219566063dSJacob Faibussowitsch       PetscCall(MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R));
57229566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R));
57239566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R));
57249566063dSJacob Faibussowitsch       PetscCall(VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R));
57259566063dSJacob Faibussowitsch       PetscCall(VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value));
572663a3b9bcSJacob 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));
57279566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
5728304d26faSStefano Zampini     }
5729684f6988SStefano Zampini   }
57305cbda25cSStefano Zampini   /* free Neumann problem's matrix */
57319566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A_RR));
5732304d26faSStefano Zampini   PetscFunctionReturn(0);
5733304d26faSStefano Zampini }
5734304d26faSStefano Zampini 
573580677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
5736674ae819SStefano Zampini {
5737674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5738be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5739b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
5740674ae819SStefano Zampini 
5741674ae819SStefano Zampini   PetscFunctionBegin;
5742b334f244SStefano Zampini   if (!reuse_solver) {
57439566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->vec1_R,0.));
574420c7b377SStefano Zampini   }
574580677318SStefano Zampini   if (!pcbddc->switch_static) {
574680677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
57479566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C));
57489566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B));
574920c7b377SStefano Zampini     }
5750b334f244SStefano Zampini     if (!reuse_solver) {
57519566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57529566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
575320c7b377SStefano Zampini     } else {
5754df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5755be83ff47SStefano Zampini 
57569566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD));
57579566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD));
575820c7b377SStefano Zampini     }
5759be83ff47SStefano Zampini   } else {
57609566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57619566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57629566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57639566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
576480677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
57659566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C));
57669566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B));
57679566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
57689566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE));
5769674ae819SStefano Zampini     }
5770674ae819SStefano Zampini   }
57719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1],pc,0,0,0));
5772b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
577380677318SStefano Zampini     if (applytranspose) {
57749566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R));
577580677318SStefano Zampini     } else {
57769566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R));
577780677318SStefano Zampini     }
57789566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec1_R));
5779be83ff47SStefano Zampini   } else {
5780df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5781be83ff47SStefano Zampini 
5782be83ff47SStefano Zampini     if (applytranspose) {
57839566063dSJacob Faibussowitsch       PetscCall(MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B));
5784be83ff47SStefano Zampini     } else {
57859566063dSJacob Faibussowitsch       PetscCall(MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B));
5786be83ff47SStefano Zampini     }
5787be83ff47SStefano Zampini   }
57889566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1],pc,0,0,0));
57899566063dSJacob Faibussowitsch   PetscCall(VecSet(inout_B,0.));
579080677318SStefano Zampini   if (!pcbddc->switch_static) {
5791b334f244SStefano Zampini     if (!reuse_solver) {
57929566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
57939566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
5794be83ff47SStefano Zampini     } else {
5795df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
5796be83ff47SStefano Zampini 
57979566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE));
57989566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE));
5799be83ff47SStefano Zampini     }
580080677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
58019566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C));
58029566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B));
580380677318SStefano Zampini     }
580480677318SStefano Zampini   } else {
58059566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
58069566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
58079566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD));
58089566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD));
580980677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
58109566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C));
58119566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R));
581280677318SStefano Zampini     }
58139566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
58149566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD));
58159566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD));
58169566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD));
5817674ae819SStefano Zampini   }
5818674ae819SStefano Zampini   PetscFunctionReturn(0);
5819674ae819SStefano Zampini }
5820674ae819SStefano Zampini 
5821dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
5822dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
5823674ae819SStefano Zampini {
5824674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
5825674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
5826674ae819SStefano Zampini   const PetscScalar zero = 0.0;
5827674ae819SStefano Zampini 
5828674ae819SStefano Zampini   PetscFunctionBegin;
5829dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
58304fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5831dc359a40SStefano Zampini     if (applytranspose) {
58329566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P));
58339566063dSJacob Faibussowitsch       if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P));
5834dc359a40SStefano Zampini     } else {
58359566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P));
58369566063dSJacob Faibussowitsch       if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P));
583715aaf578SStefano Zampini     }
58384fee134fSStefano Zampini   } else {
58399566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->vec1_P,zero));
58404fee134fSStefano Zampini   }
5841efc2fbd9SStefano Zampini 
5842efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
58434f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
5844efc2fbd9SStefano Zampini     PetscScalar *array;
58454f1b2e48SStefano Zampini     PetscInt    j;
5846efc2fbd9SStefano Zampini 
58479566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcbddc->vec1_P,&array));
58484f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
58499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcbddc->vec1_P,&array));
5850efc2fbd9SStefano Zampini   }
5851efc2fbd9SStefano Zampini 
585212edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
58539566063dSJacob Faibussowitsch   PetscCall(VecSet(pcbddc->coarse_vec,zero));
58549566063dSJacob Faibussowitsch   PetscCall(PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD));
58559566063dSJacob Faibussowitsch   PetscCall(PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD));
585612edc857SStefano Zampini 
58579f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
585812edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
585951694757SStefano Zampini     Mat          coarse_mat;
5860964fefecSStefano Zampini     Vec          rhs,sol;
586151694757SStefano Zampini     MatNullSpace nullsp;
586227b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
5863964fefecSStefano Zampini 
586427b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
586527b6a85dSStefano Zampini       PC        coarse_pc;
586627b6a85dSStefano Zampini 
58679566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc));
58689566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc));
586927b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
587027b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
587127b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
587227b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
58733bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
587427b6a85dSStefano Zampini       }
587527b6a85dSStefano Zampini     }
58769566063dSJacob Faibussowitsch     PetscCall(KSPGetRhs(pcbddc->coarse_ksp,&rhs));
58779566063dSJacob Faibussowitsch     PetscCall(KSPGetSolution(pcbddc->coarse_ksp,&sol));
58789566063dSJacob Faibussowitsch     PetscCall(KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL));
587912edc857SStefano Zampini     if (applytranspose) {
588028b400f6SJacob Faibussowitsch       PetscCheck(!pcbddc->benign_apply_coarse_only,PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
58819566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0));
58829566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol));
58839566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0));
58849566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->coarse_ksp,pc,sol));
58859566063dSJacob Faibussowitsch       PetscCall(MatGetTransposeNullSpace(coarse_mat,&nullsp));
58869bfcb8eaSStefano Zampini       if (nullsp) {
58879566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceRemove(nullsp,sol));
58889bfcb8eaSStefano Zampini       }
58892701bc32SStefano Zampini     } else {
58909566063dSJacob Faibussowitsch       PetscCall(MatGetNullSpace(coarse_mat,&nullsp));
58911f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
58922701bc32SStefano Zampini         PC        coarse_pc;
58932701bc32SStefano Zampini 
58949bfcb8eaSStefano Zampini         if (nullsp) {
58959566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceRemove(nullsp,rhs));
58969bfcb8eaSStefano Zampini         }
58979566063dSJacob Faibussowitsch         PetscCall(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc));
58989566063dSJacob Faibussowitsch         PetscCall(PCPreSolve(coarse_pc,pcbddc->coarse_ksp));
58999566063dSJacob Faibussowitsch         PetscCall(PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol));
59009566063dSJacob Faibussowitsch         PetscCall(PCPostSolve(coarse_pc,pcbddc->coarse_ksp));
590112edc857SStefano Zampini       } else {
59029566063dSJacob Faibussowitsch         PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0));
59039566063dSJacob Faibussowitsch         PetscCall(KSPSolve(pcbddc->coarse_ksp,rhs,sol));
59049566063dSJacob Faibussowitsch         PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0));
59059566063dSJacob Faibussowitsch         PetscCall(KSPCheckSolve(pcbddc->coarse_ksp,pc,sol));
59069bfcb8eaSStefano Zampini         if (nullsp) {
59079566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceRemove(nullsp,sol));
59089bfcb8eaSStefano Zampini         }
590912edc857SStefano Zampini       }
59102701bc32SStefano Zampini     }
59111d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
591227b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
591327b6a85dSStefano Zampini       PC        coarse_pc;
591427b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
591527b6a85dSStefano Zampini 
59169566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc));
591727b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
591827b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
59193bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
592027b6a85dSStefano Zampini     }
592112edc857SStefano Zampini   }
5922674ae819SStefano Zampini 
5923674ae819SStefano Zampini   /* Local solution on R nodes */
59244fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
59259566063dSJacob Faibussowitsch     PetscCall(PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose));
59269f00e9b4SStefano Zampini   }
59279f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
59289566063dSJacob Faibussowitsch   PetscCall(PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE));
59299566063dSJacob Faibussowitsch   PetscCall(PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE));
5930674ae819SStefano Zampini 
59314fee134fSStefano Zampini   /* Sum contributions from the two levels */
59324fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5933dc359a40SStefano Zampini     if (applytranspose) {
59349566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B));
59359566063dSJacob Faibussowitsch       if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D));
5936dc359a40SStefano Zampini     } else {
59379566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B));
59389566063dSJacob Faibussowitsch       if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D));
5939dc359a40SStefano Zampini     }
5940efc2fbd9SStefano Zampini     /* store p0 */
59414f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5942efc2fbd9SStefano Zampini       PetscScalar *array;
59434f1b2e48SStefano Zampini       PetscInt    j;
5944efc2fbd9SStefano Zampini 
59459566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcbddc->vec1_P,&array));
59464f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
59479566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcbddc->vec1_P,&array));
5948efc2fbd9SStefano Zampini     }
59494fee134fSStefano Zampini   } else { /* expand the coarse solution */
59504fee134fSStefano Zampini     if (applytranspose) {
59519566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B));
59524fee134fSStefano Zampini     } else {
59539566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B));
59544fee134fSStefano Zampini     }
59554fee134fSStefano Zampini   }
5956674ae819SStefano Zampini   PetscFunctionReturn(0);
5957674ae819SStefano Zampini }
5958674ae819SStefano Zampini 
595912edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5960674ae819SStefano Zampini {
5961674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
596212edc857SStefano Zampini   Vec               from,to;
59637ebab0bbSStefano Zampini   const PetscScalar *array;
5964674ae819SStefano Zampini 
5965674ae819SStefano Zampini   PetscFunctionBegin;
596612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
596712edc857SStefano Zampini     from = pcbddc->coarse_vec;
596812edc857SStefano Zampini     to = pcbddc->vec1_P;
596912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
597012edc857SStefano Zampini       Vec tvec;
597158da7f69SStefano Zampini 
59729566063dSJacob Faibussowitsch       PetscCall(KSPGetRhs(pcbddc->coarse_ksp,&tvec));
59739566063dSJacob Faibussowitsch       PetscCall(VecResetArray(tvec));
59749566063dSJacob Faibussowitsch       PetscCall(KSPGetSolution(pcbddc->coarse_ksp,&tvec));
59759566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tvec,&array));
59769566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(from,array));
59779566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tvec,&array));
597812edc857SStefano Zampini     }
597912edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
598012edc857SStefano Zampini     from = pcbddc->vec1_P;
598112edc857SStefano Zampini     to = pcbddc->coarse_vec;
598212edc857SStefano Zampini   }
59839566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode));
5984674ae819SStefano Zampini   PetscFunctionReturn(0);
5985674ae819SStefano Zampini }
5986674ae819SStefano Zampini 
598712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5988674ae819SStefano Zampini {
5989674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
599012edc857SStefano Zampini   Vec               from,to;
59917ebab0bbSStefano Zampini   const PetscScalar *array;
5992674ae819SStefano Zampini 
5993674ae819SStefano Zampini   PetscFunctionBegin;
599412edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
599512edc857SStefano Zampini     from = pcbddc->coarse_vec;
599612edc857SStefano Zampini     to = pcbddc->vec1_P;
599712edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
599812edc857SStefano Zampini     from = pcbddc->vec1_P;
599912edc857SStefano Zampini     to = pcbddc->coarse_vec;
600012edc857SStefano Zampini   }
60019566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode));
600212edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
600312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
600412edc857SStefano Zampini       Vec tvec;
600558da7f69SStefano Zampini 
60069566063dSJacob Faibussowitsch       PetscCall(KSPGetRhs(pcbddc->coarse_ksp,&tvec));
60079566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(to,&array));
60089566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(tvec,array));
60099566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(to,&array));
601058da7f69SStefano Zampini     }
601158da7f69SStefano Zampini   } else {
601258da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
60139566063dSJacob Faibussowitsch      PetscCall(VecResetArray(from));
601412edc857SStefano Zampini     }
601512edc857SStefano Zampini   }
6016674ae819SStefano Zampini   PetscFunctionReturn(0);
6017674ae819SStefano Zampini }
6018674ae819SStefano Zampini 
6019674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
6020674ae819SStefano Zampini {
6021674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
6022674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
6023674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
6024984c4197SStefano Zampini   /* one and zero */
6025984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
6026984c4197SStefano Zampini   /* space to store constraints and their local indices */
60279162d606SStefano Zampini   PetscScalar       *constraints_data;
60289162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
60299162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
60309162d606SStefano Zampini   PetscInt          *constraints_n;
6031984c4197SStefano Zampini   /* iterators */
6032b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
6033984c4197SStefano Zampini   /* BLAS integers */
6034e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
6035e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
6036c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
6037727cdba6SStefano Zampini   /* reuse */
60380e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
60390e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
6040984c4197SStefano Zampini   /* change of basis */
6041b3d85658SStefano Zampini   PetscBool         qr_needed;
60429162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
6043984c4197SStefano Zampini   /* auxiliary stuff */
604464efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
60458a0068c3SStefano Zampini   PetscInt          ncc;
6046984c4197SStefano Zampini   /* some quantities */
604745a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
6048a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
604957715f18SStefano Zampini   PetscReal         tol; /* tolerance for retaining eigenmodes */
6050984c4197SStefano Zampini 
6051674ae819SStefano Zampini   PetscFunctionBegin;
605257715f18SStefano Zampini   tol  = PetscSqrtReal(PETSC_SMALL);
60538e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
60549566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix));
60559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->ConstraintMatrix));
60569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->switch_static_change));
6057088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
6058088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
60590e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
60609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult));
60619566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc));
60629566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc));
60639566063dSJacob Faibussowitsch   PetscCall(PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult));
60649566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->primal_indices_local_idxs));
6065cf5a6209SStefano Zampini 
6066cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
60679162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
6068cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
6069cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
6070cf5a6209SStefano Zampini     Vec          *localnearnullsp;
6071cf5a6209SStefano Zampini     PetscScalar  *array;
6072cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
6073cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
6074674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
6075b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
6076674ae819SStefano Zampini     PetscScalar  *work;
6077674ae819SStefano Zampini     PetscReal    *singular_vals;
6078674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6079674ae819SStefano Zampini     PetscReal    *rwork;
6080674ae819SStefano Zampini #endif
608155080a34SStefano Zampini     PetscScalar  *temp_basis = NULL,*correlation_mat = NULL;
6082964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
6083964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
608455080a34SStefano Zampini     PetscBool    use_pod = PETSC_FALSE;
6085674ae819SStefano Zampini 
608655080a34SStefano Zampini     /* MKL SVD with same input gives different results on different processes! */
6087b88df2e7SBarry Smith #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL_LIBS)
608855080a34SStefano Zampini     use_pod = PETSC_TRUE;
608955080a34SStefano Zampini #endif
6090674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
60919566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices));
6092e4d548c7SStefano Zampini     /* print some info */
60935c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
6094e4d548c7SStefano Zampini       PetscInt nv;
6095e4d548c7SStefano Zampini 
60969566063dSJacob Faibussowitsch       PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer));
60979566063dSJacob Faibussowitsch       PetscCall(ISGetSize(ISForVertices,&nv));
60989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
60999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n"));
610063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices));
610163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges));
610263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces));
61039566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
61049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
6105e4d548c7SStefano Zampini     }
6106e4d548c7SStefano Zampini 
6107d06fc5fdSStefano Zampini     /* free unneeded index sets */
6108d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
61099566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&ISForVertices));
6110674ae819SStefano Zampini     }
6111d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
6112d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
61139566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&ISForEdges[i]));
6114d06fc5fdSStefano Zampini       }
61159566063dSJacob Faibussowitsch       PetscCall(PetscFree(ISForEdges));
6116d06fc5fdSStefano Zampini       n_ISForEdges = 0;
6117d06fc5fdSStefano Zampini     }
6118d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
6119d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
61209566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&ISForFaces[i]));
6121d06fc5fdSStefano Zampini       }
61229566063dSJacob Faibussowitsch       PetscCall(PetscFree(ISForFaces));
6123d06fc5fdSStefano Zampini       n_ISForFaces = 0;
6124d06fc5fdSStefano Zampini     }
612570022509SStefano Zampini 
6126674ae819SStefano Zampini     /* check if near null space is attached to global mat */
61276d9e27e4SStefano Zampini     if (pcbddc->use_nnsp) {
61289566063dSJacob Faibussowitsch       PetscCall(MatGetNearNullSpace(pc->pmat,&nearnullsp));
61296d9e27e4SStefano Zampini     } else nearnullsp = NULL;
61306d9e27e4SStefano Zampini 
6131674ae819SStefano Zampini     if (nearnullsp) {
61329566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs));
6133f4ddd8eeSStefano Zampini       /* remove any stored info */
61349566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace));
61359566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddc->onearnullvecs_state));
6136f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
61379566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)nearnullsp));
6138f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
61399566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state));
6140f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
61419566063dSJacob Faibussowitsch         PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]));
6142f4ddd8eeSStefano Zampini       }
6143984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
6144984c4197SStefano Zampini       nnsp_size = 0;
6145674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
6146674ae819SStefano Zampini     }
6147984c4197SStefano Zampini     /* get max number of constraints on a single cc */
6148984c4197SStefano Zampini     max_constraints = nnsp_size;
6149984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
6150984c4197SStefano Zampini 
6151674ae819SStefano Zampini     /*
6152674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
61539162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
61549162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
61559162d606SStefano Zampini          There can be multiple constraints per connected component
6156674ae819SStefano Zampini                                                                                                                                                            */
6157674ae819SStefano Zampini     n_vertices = 0;
6158674ae819SStefano Zampini     if (ISForVertices) {
61599566063dSJacob Faibussowitsch       PetscCall(ISGetSize(ISForVertices,&n_vertices));
6160674ae819SStefano Zampini     }
61619162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
61629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n));
61639162d606SStefano Zampini 
61649162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
61659162d606SStefano Zampini     total_counts *= max_constraints;
6166674ae819SStefano Zampini     total_counts += n_vertices;
61679566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(total_counts,&change_basis));
61689162d606SStefano Zampini 
6169674ae819SStefano Zampini     total_counts = 0;
6170674ae819SStefano Zampini     max_size_of_constraint = 0;
6171674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
61729162d606SStefano Zampini       IS used_is;
6173674ae819SStefano Zampini       if (i<n_ISForEdges) {
61749162d606SStefano Zampini         used_is = ISForEdges[i];
6175674ae819SStefano Zampini       } else {
61769162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
6177674ae819SStefano Zampini       }
61789566063dSJacob Faibussowitsch       PetscCall(ISGetSize(used_is,&j));
6179674ae819SStefano Zampini       total_counts += j;
6180674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
6181674ae819SStefano Zampini     }
61829566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(total_counts*max_constraints+n_vertices,&constraints_data,total_counts+n_vertices,&constraints_idxs,total_counts+n_vertices,&constraints_idxs_B));
61839162d606SStefano Zampini 
6184984c4197SStefano Zampini     /* get local part of global near null space vectors */
61859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnsp_size,&localnearnullsp));
6186984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
61879566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(pcis->vec1_N,&localnearnullsp[k]));
61889566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD));
61899566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD));
6190984c4197SStefano Zampini     }
6191674ae819SStefano Zampini 
6192242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
6193242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
6194a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
6195242a89d7SStefano Zampini 
6196984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
6197a773dcb8SStefano Zampini     if (!skip_lapack) {
6198674ae819SStefano Zampini       PetscScalar temp_work;
6199911cabfeSStefano Zampini 
620055080a34SStefano Zampini       if (use_pod) {
6201984c4197SStefano Zampini         /* Proper Orthogonal Decomposition (POD) using the snapshot method */
62029566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(max_constraints*max_constraints,&correlation_mat));
62039566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(max_constraints,&singular_vals));
62049566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis));
6205674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
62069566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(3*max_constraints,&rwork));
6207674ae819SStefano Zampini #endif
6208674ae819SStefano Zampini         /* now we evaluate the optimal workspace using query with lwork=-1 */
62099566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(max_constraints,&Blas_N));
62109566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(max_constraints,&Blas_LDA));
6211674ae819SStefano Zampini         lwork = -1;
62129566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6213674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6214c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
6215674ae819SStefano Zampini #else
6216c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
6217674ae819SStefano Zampini #endif
62189566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPop());
621928b400f6SJacob Faibussowitsch         PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
622055080a34SStefano Zampini       } else {
622155080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
6222674ae819SStefano Zampini         /* SVD */
6223674ae819SStefano Zampini         PetscInt max_n,min_n;
6224674ae819SStefano Zampini         max_n = max_size_of_constraint;
6225984c4197SStefano Zampini         min_n = max_constraints;
6226984c4197SStefano Zampini         if (max_size_of_constraint < max_constraints) {
6227674ae819SStefano Zampini           min_n = max_size_of_constraint;
6228984c4197SStefano Zampini           max_n = max_constraints;
6229674ae819SStefano Zampini         }
62309566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(min_n,&singular_vals));
6231674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
62329566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(5*min_n,&rwork));
6233674ae819SStefano Zampini #endif
6234674ae819SStefano Zampini         /* now we evaluate the optimal workspace using query with lwork=-1 */
6235674ae819SStefano Zampini         lwork = -1;
62369566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(max_n,&Blas_M));
62379566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(min_n,&Blas_N));
62389566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(max_n,&Blas_LDA));
62399566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6240674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
62419162d606SStefano 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));
6242674ae819SStefano Zampini #else
62439162d606SStefano 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));
6244674ae819SStefano Zampini #endif
62459566063dSJacob Faibussowitsch         PetscCall(PetscFPTrapPop());
624628b400f6SJacob Faibussowitsch         PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
624755080a34SStefano Zampini #else
624855080a34SStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen");
6249984c4197SStefano Zampini #endif /* on missing GESVD */
625055080a34SStefano Zampini       }
6251674ae819SStefano Zampini       /* Allocate optimal workspace */
62529566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork));
62539566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(lwork,&work));
6254674ae819SStefano Zampini     }
6255674ae819SStefano Zampini     /* Now we can loop on constraining sets */
6256674ae819SStefano Zampini     total_counts = 0;
62579162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
62589162d606SStefano Zampini     constraints_data_ptr[0] = 0;
6259674ae819SStefano Zampini     /* vertices */
62609162d606SStefano Zampini     if (n_vertices) {
62619566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(ISForVertices,(const PetscInt**)&is_indices));
62629566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(constraints_idxs,is_indices,n_vertices));
6263674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
62649162d606SStefano Zampini         constraints_n[total_counts] = 1;
62659162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
62669162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
62679162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
6268674ae819SStefano Zampini         total_counts++;
6269674ae819SStefano Zampini       }
62709566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices));
6271674ae819SStefano Zampini       n_vertices = total_counts;
6272674ae819SStefano Zampini     }
6273984c4197SStefano Zampini 
6274674ae819SStefano Zampini     /* edges and faces */
62759162d606SStefano Zampini     total_counts_cc = total_counts;
6276911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
62779162d606SStefano Zampini       IS        used_is;
62789162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
62799162d606SStefano Zampini 
6280911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
62819162d606SStefano Zampini         used_is = ISForEdges[ncc];
6282984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
6283674ae819SStefano Zampini       } else {
62849162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
6285984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
6286674ae819SStefano Zampini       }
6287674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
62889162d606SStefano Zampini 
62899566063dSJacob Faibussowitsch       PetscCall(ISGetSize(used_is,&size_of_constraint));
62909566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(used_is,(const PetscInt**)&is_indices));
6291984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
6292984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
6293674ae819SStefano Zampini       if (nnsp_has_cnst) {
62945b08dc53SStefano Zampini         PetscScalar quad_value;
62959162d606SStefano Zampini 
62969566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint));
62979162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
62989162d606SStefano Zampini 
6299a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
6300674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
6301a773dcb8SStefano Zampini         } else {
6302a773dcb8SStefano Zampini           quad_value = 1.0;
6303a773dcb8SStefano Zampini         }
6304674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
63059162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
6306674ae819SStefano Zampini         }
63079162d606SStefano Zampini         temp_constraints++;
6308674ae819SStefano Zampini         total_counts++;
6309674ae819SStefano Zampini       }
6310674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
6311984c4197SStefano Zampini         PetscReal real_value;
63129162d606SStefano Zampini         PetscScalar *ptr_to_data;
63139162d606SStefano Zampini 
63149566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array));
63159162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
6316674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
63179162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
6318674ae819SStefano Zampini         }
63199566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array));
6320984c4197SStefano Zampini         /* check if array is null on the connected component */
63219566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
63229162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
632357715f18SStefano Zampini         if (real_value > tol*size_of_constraint) { /* keep indices and values */
6324674ae819SStefano Zampini           temp_constraints++;
6325674ae819SStefano Zampini           total_counts++;
63269162d606SStefano Zampini           if (!idxs_copied) {
63279566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint));
63289162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
6329674ae819SStefano Zampini           }
6330674ae819SStefano Zampini         }
63319162d606SStefano Zampini       }
63329566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(used_is,(const PetscInt**)&is_indices));
633345a1bb75SStefano Zampini       valid_constraints = temp_constraints;
6334eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
6335a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
63369162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
63379162d606SStefano Zampini 
63389162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
63399566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
63409162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
6341a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
63429162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
6343a773dcb8SStefano Zampini         } else { /* perform SVD */
63449162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
6345674ae819SStefano Zampini 
634655080a34SStefano Zampini           if (use_pod) {
6347984c4197SStefano Zampini             /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
6348984c4197SStefano Zampini                POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
6349984c4197SStefano Zampini                -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
6350984c4197SStefano Zampini                   the constraints basis will differ (by a complex factor with absolute value equal to 1)
6351984c4197SStefano Zampini                   from that computed using LAPACKgesvd
6352984c4197SStefano Zampini                -> This is due to a different computation of eigenvectors in LAPACKheev
6353984c4197SStefano Zampini                -> The quality of the POD-computed basis will be the same */
63549566063dSJacob Faibussowitsch             PetscCall(PetscArrayzero(correlation_mat,temp_constraints*temp_constraints));
6355674ae819SStefano Zampini             /* Store upper triangular part of correlation matrix */
63569566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
63579566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6358674ae819SStefano Zampini             for (j=0;j<temp_constraints;j++) {
6359674ae819SStefano Zampini               for (k=0;k<j+1;k++) {
63609162d606SStefano 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));
6361674ae819SStefano Zampini               }
6362674ae819SStefano Zampini             }
6363e310c8b4SStefano Zampini             /* compute eigenvalues and eigenvectors of correlation matrix */
63649566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_N));
63659566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_LDA));
6366674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
6367c8244a33SStefano Zampini             PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
6368674ae819SStefano Zampini #else
6369c8244a33SStefano Zampini             PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
6370674ae819SStefano Zampini #endif
63719566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPop());
637228b400f6SJacob Faibussowitsch             PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
6373984c4197SStefano Zampini             /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
6374674ae819SStefano Zampini             j = 0;
637587b3baaaSStefano Zampini             while (j < temp_constraints && singular_vals[j]/singular_vals[temp_constraints-1] < tol) j++;
6376674ae819SStefano Zampini             total_counts = total_counts-j;
637745a1bb75SStefano Zampini             valid_constraints = temp_constraints-j;
6378e310c8b4SStefano Zampini             /* scale and copy POD basis into used quadrature memory */
63799566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
63809566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_N));
63819566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_K));
63829566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
63839566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_LDB));
63849566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDC));
6385674ae819SStefano Zampini             if (j<temp_constraints) {
6386984c4197SStefano Zampini               PetscInt ii;
6387984c4197SStefano Zampini               for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
63889566063dSJacob Faibussowitsch               PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
63899162d606SStefano 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));
63909566063dSJacob Faibussowitsch               PetscCall(PetscFPTrapPop());
6391984c4197SStefano Zampini               for (k=0;k<temp_constraints-j;k++) {
6392674ae819SStefano Zampini                 for (ii=0;ii<size_of_constraint;ii++) {
63939162d606SStefano 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];
6394674ae819SStefano Zampini                 }
6395674ae819SStefano Zampini               }
6396674ae819SStefano Zampini             }
639755080a34SStefano Zampini           } else {
639855080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
63999566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
64009566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(temp_constraints,&Blas_N));
64019566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
64029566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6403674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
64049162d606SStefano 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));
6405674ae819SStefano Zampini #else
64069162d606SStefano 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));
6407674ae819SStefano Zampini #endif
640828b400f6SJacob Faibussowitsch             PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
64099566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPop());
6410984c4197SStefano Zampini             /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
6411e310c8b4SStefano Zampini             k = temp_constraints;
6412e310c8b4SStefano Zampini             if (k > size_of_constraint) k = size_of_constraint;
6413674ae819SStefano Zampini             j = 0;
641487b3baaaSStefano Zampini             while (j < k && singular_vals[k-j-1]/singular_vals[0] < tol) j++;
641545a1bb75SStefano Zampini             valid_constraints = k-j;
6416911cabfeSStefano Zampini             total_counts = total_counts-temp_constraints+valid_constraints;
641755080a34SStefano Zampini #else
641855080a34SStefano Zampini             SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen");
6419984c4197SStefano Zampini #endif /* on missing GESVD */
6420674ae819SStefano Zampini           }
6421a773dcb8SStefano Zampini         }
642255080a34SStefano Zampini       }
64239162d606SStefano Zampini       /* update pointers information */
64249162d606SStefano Zampini       if (valid_constraints) {
64259162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
64269162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
64279162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
64289162d606SStefano Zampini         /* set change_of_basis flag */
642945a1bb75SStefano Zampini         if (boolforchange) {
6430b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
64319162d606SStefano Zampini         }
6432b3d85658SStefano Zampini         total_counts_cc++;
643345a1bb75SStefano Zampini       }
643445a1bb75SStefano Zampini     }
6435984c4197SStefano Zampini     /* free workspace */
64368f1c130eSStefano Zampini     if (!skip_lapack) {
64379566063dSJacob Faibussowitsch       PetscCall(PetscFree(work));
6438984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
64399566063dSJacob Faibussowitsch       PetscCall(PetscFree(rwork));
6440984c4197SStefano Zampini #endif
64419566063dSJacob Faibussowitsch       PetscCall(PetscFree(singular_vals));
64429566063dSJacob Faibussowitsch       PetscCall(PetscFree(correlation_mat));
64439566063dSJacob Faibussowitsch       PetscCall(PetscFree(temp_basis));
6444984c4197SStefano Zampini     }
6445984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
64469566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&localnearnullsp[k]));
6447984c4197SStefano Zampini     }
64489566063dSJacob Faibussowitsch     PetscCall(PetscFree(localnearnullsp));
6449cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
6450cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
64519566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&ISForFaces[i]));
6452cf5a6209SStefano Zampini     }
6453cf5a6209SStefano Zampini     if (n_ISForFaces) {
64549566063dSJacob Faibussowitsch       PetscCall(PetscFree(ISForFaces));
6455cf5a6209SStefano Zampini     }
6456cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
64579566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&ISForEdges[i]));
6458cf5a6209SStefano Zampini     }
6459cf5a6209SStefano Zampini     if (n_ISForEdges) {
64609566063dSJacob Faibussowitsch       PetscCall(PetscFree(ISForEdges));
6461cf5a6209SStefano Zampini     }
64629566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ISForVertices));
646308122e43SStefano Zampini   } else {
646408122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
6465984c4197SStefano Zampini 
646608122e43SStefano Zampini     total_counts = 0;
646708122e43SStefano Zampini     n_vertices = 0;
6468d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
64699566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(sub_schurs->is_vertices,&n_vertices));
647008122e43SStefano Zampini     }
647108122e43SStefano Zampini     max_constraints = 0;
64729162d606SStefano Zampini     total_counts_cc = 0;
647308122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
647408122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
64759162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
647608122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
647708122e43SStefano Zampini     }
64789162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
64799162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
64809162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
64819162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
648274d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
64839566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(total_counts_cc,&constraints_n));
64849162d606SStefano Zampini     total_counts_cc = 0;
64859162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
64869162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
64879162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
648808122e43SStefano Zampini       }
648908122e43SStefano Zampini     }
649008122e43SStefano Zampini 
64918bec7fa6SStefano Zampini     max_size_of_constraint = 0;
64929162d606SStefano 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]);
64939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B));
649408122e43SStefano Zampini     /* Change of basis */
64959566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(total_counts_cc,&change_basis));
649608122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
649708122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
649808122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
64999566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(change_basis,i+n_vertices));
650008122e43SStefano Zampini         }
650108122e43SStefano Zampini       }
650208122e43SStefano Zampini     }
650308122e43SStefano Zampini   }
6504984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
65059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs));
650608122e43SStefano Zampini 
65079162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
65089566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B));
650963a3b9bcSJacob 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);
6510674ae819SStefano Zampini 
6511674ae819SStefano Zampini   /* Create constraint matrix */
65129566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix));
65139566063dSJacob Faibussowitsch   PetscCall(MatSetType(pcbddc->ConstraintMatrix,MATAIJ));
65149566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n));
6515984c4197SStefano Zampini 
6516984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
6517a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
65185a52fde0SStefano Zampini   qr_needed = pcbddc->use_qr_single;
65199566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(total_counts_cc,&qr_needed_idx));
6520984c4197SStefano Zampini   total_primal_vertices=0;
6521b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
65229162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
65239162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
652472b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
65259162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
6526b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
652764efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
65289162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
65299162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
6530a717540cSStefano Zampini       }
6531b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
653291af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
6533a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
6534a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
6535a717540cSStefano Zampini       }
6536fa434743SStefano Zampini     } else {
6537b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
6538fa434743SStefano Zampini     }
6539a717540cSStefano Zampini   }
6540b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
6541b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
6542674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
65439566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs));
65449566063dSJacob 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));
65459566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices));
65460e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
6547984c4197SStefano Zampini 
6548984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
654974d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
65509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pcbddc->local_primal_size,&nnz));
6551984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
655274d5cdf7SStefano Zampini 
6553984c4197SStefano Zampini   j = total_primal_vertices;
655474d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
6555b3d85658SStefano Zampini   cum = total_primal_vertices;
65569162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
65574641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
6558b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
6559b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
6560b3d85658SStefano Zampini       cum++;
65619162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
656274d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
656374d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
656474d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
656574d5cdf7SStefano Zampini       }
65669162d606SStefano Zampini       j += constraints_n[i];
6567674ae819SStefano Zampini     }
6568674ae819SStefano Zampini   }
65699566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz));
65709566063dSJacob Faibussowitsch   PetscCall(MatSetOption(pcbddc->ConstraintMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
65719566063dSJacob Faibussowitsch   PetscCall(PetscFree(nnz));
6572088faed8SStefano Zampini 
6573674ae819SStefano Zampini   /* set values in constraint matrix */
6574984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
65759566063dSJacob Faibussowitsch     PetscCall(MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES));
6576674ae819SStefano Zampini   }
6577984c4197SStefano Zampini   total_counts = total_primal_vertices;
65789162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
65794641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
65809162d606SStefano Zampini       PetscInt *cols;
65819162d606SStefano Zampini 
65829162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
65839162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
65849162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
65859162d606SStefano Zampini         PetscInt    row = total_counts+k;
65869162d606SStefano Zampini         PetscScalar *vals;
65879162d606SStefano Zampini 
65889162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
65899566063dSJacob Faibussowitsch         PetscCall(MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES));
65909162d606SStefano Zampini       }
65919162d606SStefano Zampini       total_counts += constraints_n[i];
6592674ae819SStefano Zampini     }
6593674ae819SStefano Zampini   }
6594674ae819SStefano Zampini   /* assembling */
65959566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY));
65969566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY));
65979566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(pcbddc->ConstraintMatrix,(PetscObject)pc,"-pc_bddc_constraint_mat_view"));
6598088faed8SStefano Zampini 
6599674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
6600674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
6601026de310SStefano Zampini     /* dual and primal dofs on a single cc */
6602984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
6603984c4197SStefano Zampini     /* working stuff for GEQRF */
66045a52fde0SStefano Zampini     PetscScalar  *qr_basis = NULL,*qr_tau = NULL,*qr_work = NULL,lqr_work_t;
6605984c4197SStefano Zampini     PetscBLASInt lqr_work;
6606984c4197SStefano Zampini     /* working stuff for UNGQR */
66073c377650SSatish Balay     PetscScalar  *gqr_work = NULL,lgqr_work_t=0.0;
6608984c4197SStefano Zampini     PetscBLASInt lgqr_work;
6609984c4197SStefano Zampini     /* working stuff for TRTRS */
66105a52fde0SStefano Zampini     PetscScalar  *trs_rhs = NULL;
66113f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
6612984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
6613984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
6614984c4197SStefano Zampini     PetscScalar  *start_vals;
6615984c4197SStefano Zampini     /* working stuff for values insertion */
66164641a718SStefano Zampini     PetscBT      is_primal;
661764efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
6618906d46d4SStefano Zampini     /* matrix sizes */
6619906d46d4SStefano Zampini     PetscInt     global_size,local_size;
6620906d46d4SStefano Zampini     /* temporary change of basis */
6621906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
6622cf5a6209SStefano Zampini     /* extra space for debugging */
66235a52fde0SStefano Zampini     PetscScalar  *dbg_work = NULL;
6624984c4197SStefano Zampini 
6625906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
66269566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix));
66279566063dSJacob Faibussowitsch     PetscCall(MatSetType(localChangeOfBasisMatrix,MATAIJ));
66289566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n));
6629906d46d4SStefano Zampini     /* nonzeros for local mat */
66309566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n,&nnz));
66311dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6632bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
66331dd7afcfSStefano Zampini     } else {
66341dd7afcfSStefano Zampini       const PetscInt *ii;
66351dd7afcfSStefano Zampini       PetscInt       n;
66361dd7afcfSStefano Zampini       PetscBool      flg_row;
66379566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row));
66381dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
66399566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row));
66401dd7afcfSStefano Zampini     }
66419162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
6642a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
66439162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
6644a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
66459162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
6646a717540cSStefano Zampini         } else {
66479162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
66489162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
6649a717540cSStefano Zampini         }
6650a717540cSStefano Zampini       }
6651a717540cSStefano Zampini     }
66529566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz));
66539566063dSJacob Faibussowitsch     PetscCall(MatSetOption(localChangeOfBasisMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
66549566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz));
66551dd7afcfSStefano Zampini     /* Set interior change in the matrix */
66561dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
6657bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
66589566063dSJacob Faibussowitsch         PetscCall(MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES));
6659a717540cSStefano Zampini       }
66601dd7afcfSStefano Zampini     } else {
66611dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
66621dd7afcfSStefano Zampini       PetscScalar    *aa;
66631dd7afcfSStefano Zampini       PetscInt       n;
66641dd7afcfSStefano Zampini       PetscBool      flg_row;
66659566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row));
66669566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(pcbddc->benign_change,&aa));
66671dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
66689566063dSJacob Faibussowitsch         PetscCall(MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES));
66691dd7afcfSStefano Zampini       }
66709566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJRestoreArray(pcbddc->benign_change,&aa));
66719566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row));
66721dd7afcfSStefano Zampini     }
6673a717540cSStefano Zampini 
6674a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
66759566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n"));
66769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank));
6677a717540cSStefano Zampini     }
6678a717540cSStefano Zampini 
6679a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
6680a717540cSStefano Zampini     /*
6681a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
6682a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
6683a717540cSStefano Zampini 
6684a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
6685a717540cSStefano Zampini 
6686a6b551f4SStefano Zampini           - Using the following block transformation if there is only a primal dof on the cc (and -pc_bddc_use_qr_single is not specified)
6687a6b551f4SStefano Zampini 
6688a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
6689a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
6690a717540cSStefano Zampini             |              ...                        |
6691a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
6692a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
6693a717540cSStefano Zampini 
6694a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
6695a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
6696a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
6697a6b551f4SStefano Zampini 
6698a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
6699a717540cSStefano Zampini     */
67005a52fde0SStefano Zampini     if (qr_needed && max_size_of_constraint) {
6701984c4197SStefano Zampini       /* space to store Q */
67029566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis));
67034e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
67049566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(max_constraints,&qr_tau));
6705984c4197SStefano Zampini       /* first we issue queries for optimal work */
67069566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_M));
67079566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_constraints,&Blas_N));
67089566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_LDA));
6709984c4197SStefano Zampini       lqr_work = -1;
67103f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
671128b400f6SJacob Faibussowitsch       PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
67129566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work));
67139566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work));
6714984c4197SStefano Zampini       lgqr_work = -1;
67159566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_M));
67169566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_N));
67179566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_constraints,&Blas_K));
67189566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast(max_size_of_constraint,&Blas_LDA));
67193f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
6720c964aadfSJose E. Roman       PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
672128b400f6SJacob Faibussowitsch       PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr);
67229566063dSJacob Faibussowitsch       PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work));
67239566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work));
6724984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
67259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(max_constraints*max_constraints,&trs_rhs));
6726a717540cSStefano Zampini       /* allocating workspace for check */
6727a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
67289566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work));
6729a717540cSStefano Zampini       }
6730a717540cSStefano Zampini     }
6731984c4197SStefano Zampini     /* array to store whether a node is primal or not */
67329566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(pcis->n_B,&is_primal));
67339566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B));
67349566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B));
673563a3b9bcSJacob 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);
673639e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
67379566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(is_primal,aux_primal_numbering_B[i]));
673839e2fb2aSStefano Zampini     }
67399566063dSJacob Faibussowitsch     PetscCall(PetscFree(aux_primal_numbering_B));
6740984c4197SStefano Zampini 
6741a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
67429162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
67439162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
67444641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
6745984c4197SStefano Zampini         /* get constraint info */
67469162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
6747984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
6748984c4197SStefano Zampini 
6749984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
675063a3b9bcSJacob 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));
6751674ae819SStefano Zampini         }
6752984c4197SStefano Zampini 
6753fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
6754a717540cSStefano Zampini 
6755a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
6756a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
67579566063dSJacob Faibussowitsch             PetscCall(PetscArraycpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs));
6758a717540cSStefano Zampini           }
6759984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
67609566063dSJacob Faibussowitsch           PetscCall(PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs));
6761984c4197SStefano Zampini 
6762984c4197SStefano Zampini           /* compute QR decomposition of constraints */
67639566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
67649566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_N));
67659566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
67669566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
67673f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
676828b400f6SJacob Faibussowitsch           PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
67699566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
6770984c4197SStefano Zampini 
6771a5b23f4aSJose E. Roman           /* explicitly compute R^-T */
67729566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(trs_rhs,primal_dofs*primal_dofs));
6773984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
67749566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_N));
67759566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_NRHS));
67769566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
67779566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_LDB));
67789566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
67793f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
678028b400f6SJacob Faibussowitsch           PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
67819566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
6782984c4197SStefano Zampini 
6783a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */
67849566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
67859566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
67869566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_K));
67879566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
67889566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6789c964aadfSJose E. Roman           PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
679028b400f6SJacob Faibussowitsch           PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr);
67919566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
6792984c4197SStefano Zampini 
6793984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
6794984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
6795984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
67969566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_M));
67979566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_N));
67989566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_K));
67999566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
68009566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(primal_dofs,&Blas_LDB));
68019566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDC));
68029566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
68039162d606SStefano 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));
68049566063dSJacob Faibussowitsch           PetscCall(PetscFPTrapPop());
68059566063dSJacob Faibussowitsch           PetscCall(PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs));
6806984c4197SStefano Zampini 
6807984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
68089162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
6809984c4197SStefano Zampini           /* insert cols for primal dofs */
6810984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
6811984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
68129162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
68139566063dSJacob Faibussowitsch             PetscCall(MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES));
6814984c4197SStefano Zampini           }
6815984c4197SStefano Zampini           /* insert cols for dual dofs */
6816984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
68179162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
6818984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
68199162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
68209566063dSJacob Faibussowitsch               PetscCall(MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES));
6821984c4197SStefano Zampini               j++;
6822674ae819SStefano Zampini             }
6823674ae819SStefano Zampini           }
6824984c4197SStefano Zampini 
6825984c4197SStefano Zampini           /* check change of basis */
6826984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
6827984c4197SStefano Zampini             PetscInt   ii,jj;
6828984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
68299566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(primal_dofs,&Blas_M));
68309566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
68319566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_K));
68329566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDA));
68339566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_LDB));
68349566063dSJacob Faibussowitsch             PetscCall(PetscBLASIntCast(primal_dofs,&Blas_LDC));
68359566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
6836cf5a6209SStefano 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));
68379566063dSJacob Faibussowitsch             PetscCall(PetscFPTrapPop());
6838984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
6839984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
6840cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
6841c068d9bbSLisandro 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;
6842674ae819SStefano Zampini               }
6843674ae819SStefano Zampini             }
6844984c4197SStefano Zampini             if (!valid_qr) {
68459566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n"));
6846984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
6847984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
6848cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
684963a3b9bcSJacob 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])));
6850674ae819SStefano Zampini                   }
6851c068d9bbSLisandro Dalcin                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) {
685263a3b9bcSJacob 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])));
6853984c4197SStefano Zampini                   }
6854984c4197SStefano Zampini                 }
6855984c4197SStefano Zampini               }
6856674ae819SStefano Zampini             } else {
68579566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n"));
6858674ae819SStefano Zampini             }
6859674ae819SStefano Zampini           }
6860a717540cSStefano Zampini         } else { /* simple transformation block */
6861a717540cSStefano Zampini           PetscInt    row,col;
6862a6b551f4SStefano Zampini           PetscScalar val,norm;
6863a6b551f4SStefano Zampini 
68649566063dSJacob Faibussowitsch           PetscCall(PetscBLASIntCast(size_of_constraint,&Blas_N));
68659162d606SStefano 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));
6866a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
68679162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
68689162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6869bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
68709162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
68719566063dSJacob Faibussowitsch               PetscCall(MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES));
68729566063dSJacob Faibussowitsch               PetscCall(MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES));
6873a717540cSStefano Zampini             } else {
6874a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
68759162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6876a717540cSStefano Zampini                 if (row != col) {
68779162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6878a717540cSStefano Zampini                 } else {
68799162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6880a717540cSStefano Zampini                 }
68819566063dSJacob Faibussowitsch                 PetscCall(MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES));
6882a717540cSStefano Zampini               }
6883a717540cSStefano Zampini             }
6884a717540cSStefano Zampini           }
688598a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
68869566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n"));
6887a717540cSStefano Zampini           }
6888674ae819SStefano Zampini         }
6889984c4197SStefano Zampini       } else {
6890984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
689163a3b9bcSJacob 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));
6892674ae819SStefano Zampini         }
6893674ae819SStefano Zampini       }
6894674ae819SStefano Zampini     }
6895a717540cSStefano Zampini 
6896a717540cSStefano Zampini     /* free workspace */
6897a717540cSStefano Zampini     if (qr_needed) {
6898984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
68999566063dSJacob Faibussowitsch         PetscCall(PetscFree(dbg_work));
6900984c4197SStefano Zampini       }
69019566063dSJacob Faibussowitsch       PetscCall(PetscFree(trs_rhs));
69029566063dSJacob Faibussowitsch       PetscCall(PetscFree(qr_tau));
69039566063dSJacob Faibussowitsch       PetscCall(PetscFree(qr_work));
69049566063dSJacob Faibussowitsch       PetscCall(PetscFree(gqr_work));
69059566063dSJacob Faibussowitsch       PetscCall(PetscFree(qr_basis));
6906674ae819SStefano Zampini     }
69079566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&is_primal));
69089566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY));
69099566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY));
6910906d46d4SStefano Zampini 
6911906d46d4SStefano Zampini     /* assembling of global change of variable */
691288c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6913bbb9e6c6SStefano Zampini       Mat      tmat;
691416f15bc4SStefano Zampini       PetscInt bs;
691516f15bc4SStefano Zampini 
69169566063dSJacob Faibussowitsch       PetscCall(VecGetSize(pcis->vec1_global,&global_size));
69179566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(pcis->vec1_global,&local_size));
69189566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat));
69199566063dSJacob Faibussowitsch       PetscCall(MatISSetLocalMat(tmat,localChangeOfBasisMatrix));
69209566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY));
69219566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY));
69229566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix));
69239566063dSJacob Faibussowitsch       PetscCall(MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ));
69249566063dSJacob Faibussowitsch       PetscCall(MatGetBlockSize(pc->pmat,&bs));
69259566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs));
69269566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size));
69279566063dSJacob Faibussowitsch       PetscCall(MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE));
69289566063dSJacob Faibussowitsch       PetscCall(MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix));
69299566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&tmat));
69309566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global,0.0));
69319566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_N,1.0));
69329566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
69339566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
69349566063dSJacob Faibussowitsch       PetscCall(VecReciprocal(pcis->vec1_global));
69359566063dSJacob Faibussowitsch       PetscCall(MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL));
693688c03ad3SStefano Zampini 
6937906d46d4SStefano Zampini       /* check */
6938906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6939906d46d4SStefano Zampini         PetscReal error;
6940906d46d4SStefano Zampini         Vec       x,x_change;
6941906d46d4SStefano Zampini 
69429566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(pcis->vec1_global,&x));
69439566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(pcis->vec1_global,&x_change));
69449566063dSJacob Faibussowitsch         PetscCall(VecSetRandom(x,NULL));
69459566063dSJacob Faibussowitsch         PetscCall(VecCopy(x,pcis->vec1_global));
69469566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
69479566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
69489566063dSJacob Faibussowitsch         PetscCall(MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N));
69499566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE));
69509566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE));
69519566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change));
69529566063dSJacob Faibussowitsch         PetscCall(VecAXPY(x,-1.0,x_change));
69539566063dSJacob Faibussowitsch         PetscCall(VecNorm(x,NORM_INFINITY,&error));
6954637e8532SStefano Zampini         if (error > PETSC_SMALL) {
695563a3b9bcSJacob Faibussowitsch           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",(double)error);
6956637e8532SStefano Zampini         }
69579566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&x));
69589566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&x_change));
6959906d46d4SStefano Zampini       }
6960b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6961b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6962b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6963bf3a8328SStefano Zampini 
696408401ef6SPierre 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");
6965b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6966ac632422SStefano Zampini           Mat                    S_new,tmat;
6967bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6968bbb9e6c6SStefano Zampini 
69699566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N));
69709566063dSJacob Faibussowitsch           PetscCall(MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat));
6971bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6972bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6973bf3a8328SStefano Zampini             IS                     is_V;
69749566063dSJacob Faibussowitsch             PetscCall(ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V));
69759566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall));
69769566063dSJacob Faibussowitsch             PetscCall(ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall));
69779566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingDestroy(&NtoSall));
69789566063dSJacob Faibussowitsch             PetscCall(ISDestroy(&is_V));
6979bf3a8328SStefano Zampini           }
69809566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&is_all_N));
69819566063dSJacob Faibussowitsch           PetscCall(MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new));
69829566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&sub_schurs->S_Ej_all));
69839566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)S_new));
6984bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6985bf3a8328SStefano Zampini             const PetscScalar *array;
6986bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6987bf3a8328SStefano Zampini             PetscInt          i,n_V;
6988bf3a8328SStefano Zampini 
69899566063dSJacob Faibussowitsch             PetscCall(MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL));
69909566063dSJacob Faibussowitsch             PetscCall(ISGetLocalSize(is_V_Sall,&n_V));
69919566063dSJacob Faibussowitsch             PetscCall(ISGetIndices(is_V_Sall,&idxs_V));
69929566063dSJacob Faibussowitsch             PetscCall(ISGetIndices(sub_schurs->is_Ej_all,&idxs_all));
69939566063dSJacob Faibussowitsch             PetscCall(VecGetArrayRead(pcis->D,&array));
6994b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6995b087196eSStefano Zampini               PetscScalar val;
6996b087196eSStefano Zampini               PetscInt    idx;
6997b087196eSStefano Zampini 
6998b087196eSStefano Zampini               idx = idxs_V[i];
6999b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
70009566063dSJacob Faibussowitsch               PetscCall(MatSetValue(S_new,idx,idx,val,INSERT_VALUES));
7001b087196eSStefano Zampini             }
70029566063dSJacob Faibussowitsch             PetscCall(MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY));
70039566063dSJacob Faibussowitsch             PetscCall(MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY));
70049566063dSJacob Faibussowitsch             PetscCall(VecRestoreArrayRead(pcis->D,&array));
70059566063dSJacob Faibussowitsch             PetscCall(ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all));
70069566063dSJacob Faibussowitsch             PetscCall(ISRestoreIndices(is_V_Sall,&idxs_V));
7007bf3a8328SStefano Zampini           }
7008ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
70099566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&S_new));
7010ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
70119566063dSJacob Faibussowitsch             PetscCall(MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new));
70129566063dSJacob Faibussowitsch             PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_all));
70139566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)S_new));
7014bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
70159566063dSJacob Faibussowitsch               PetscCall(MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL));
7016bf3a8328SStefano Zampini             }
7017ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
70189566063dSJacob Faibussowitsch             PetscCall(MatDestroy(&S_new));
7019ac632422SStefano Zampini           }
70209566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&is_V_Sall));
70219566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&tmat));
7022b96c3477SStefano Zampini         }
7023c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
7024b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
7025c9db6a07SStefano Zampini           PetscInt i;
7026c9db6a07SStefano Zampini 
7027c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
70289566063dSJacob Faibussowitsch             PetscCall(KSPDestroy(&sub_schurs->change[i]));
7029c9db6a07SStefano Zampini           }
70309566063dSJacob Faibussowitsch           PetscCall(PetscFree(sub_schurs->change));
7031c9db6a07SStefano Zampini         }
7032b96c3477SStefano Zampini       }
703316909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
703416909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
703516909a7fSStefano Zampini       } else {
70369566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&localChangeOfBasisMatrix));
703716909a7fSStefano Zampini       }
70381dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
703927b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
704072b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
70419566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->ConstraintMatrix));
704272b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
704372b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
704472b8c272SStefano Zampini     }
70451dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
704627b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
70479566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix));
7048b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
7049906d46d4SStefano Zampini     } else {
70501dd7afcfSStefano Zampini       Mat benign_global = NULL;
705127b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
70521dd7afcfSStefano Zampini         Mat M;
70531dd7afcfSStefano Zampini 
70549e9b7b1fSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
70559566063dSJacob Faibussowitsch         PetscCall(VecCopy(matis->counter,pcis->vec1_N));
70569566063dSJacob Faibussowitsch         PetscCall(VecReciprocal(pcis->vec1_N));
70579566063dSJacob Faibussowitsch         PetscCall(MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&benign_global));
70589e9b7b1fSStefano Zampini         if (pcbddc->benign_change) {
70599566063dSJacob Faibussowitsch           PetscCall(MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M));
70609566063dSJacob Faibussowitsch           PetscCall(MatDiagonalScale(M,pcis->vec1_N,NULL));
7061906d46d4SStefano Zampini         } else {
70629566063dSJacob Faibussowitsch           PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&M));
70639566063dSJacob Faibussowitsch           PetscCall(MatDiagonalSet(M,pcis->vec1_N,INSERT_VALUES));
7064906d46d4SStefano Zampini         }
70659566063dSJacob Faibussowitsch         PetscCall(MatISSetLocalMat(benign_global,M));
70669566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&M));
70679566063dSJacob Faibussowitsch         PetscCall(MatAssemblyBegin(benign_global,MAT_FINAL_ASSEMBLY));
70689566063dSJacob Faibussowitsch         PetscCall(MatAssemblyEnd(benign_global,MAT_FINAL_ASSEMBLY));
70691dd7afcfSStefano Zampini       }
70701dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
70719566063dSJacob Faibussowitsch         PetscCall(MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix));
70729566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&benign_global));
707327b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
70741dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
70751dd7afcfSStefano Zampini       }
70761dd7afcfSStefano Zampini     }
707716909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
707816909a7fSStefano Zampini       IS             is_global;
707916909a7fSStefano Zampini       const PetscInt *gidxs;
708016909a7fSStefano Zampini 
70819566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&gidxs));
70829566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global));
70839566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&gidxs));
70849566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change));
70859566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is_global));
708616909a7fSStefano Zampini     }
70871dd7afcfSStefano Zampini   }
70881dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
70899566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->work_change));
7090b9b85e73SStefano Zampini   }
7091a717540cSStefano Zampini 
709272b8c272SStefano Zampini   if (!pcbddc->fake_change) {
70934f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
70944f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
70954f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
70964f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
7097019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
7098019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
7099019a44ceSStefano Zampini       pcbddc->local_primal_size++;
7100019a44ceSStefano Zampini     }
7101019a44ceSStefano Zampini 
7102019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
7103727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
7104727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
71059566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc,&pcbddc->new_primal_space_local));
7106c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
71070e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
71089566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc,&pcbddc->new_primal_space_local));
7109727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
7110727cdba6SStefano Zampini       }
71110e6343abSStefano Zampini     }
7112727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
71131c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
711472b8c272SStefano Zampini   }
71159566063dSJacob Faibussowitsch   PetscCall(PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult));
7116727cdba6SStefano Zampini 
7117a717540cSStefano Zampini   /* flush dbg viewer */
7118b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
71199566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
7120b8ffe317SStefano Zampini   }
7121a717540cSStefano Zampini 
7122e310c8b4SStefano Zampini   /* free workspace */
71239566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&qr_needed_idx));
71249566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&change_basis));
712508122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
71269566063dSJacob Faibussowitsch     PetscCall(PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n));
71279566063dSJacob Faibussowitsch     PetscCall(PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B));
712808122e43SStefano Zampini   } else {
7129d0609cedSBarry 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));
71309566063dSJacob Faibussowitsch     PetscCall(PetscFree(constraints_n));
71319566063dSJacob Faibussowitsch     PetscCall(PetscFree(constraints_idxs_B));
713208122e43SStefano Zampini   }
7133674ae819SStefano Zampini   PetscFunctionReturn(0);
7134674ae819SStefano Zampini }
7135674ae819SStefano Zampini 
7136674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
7137674ae819SStefano Zampini {
713871582508SStefano Zampini   ISLocalToGlobalMapping map;
7139674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7140674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
714166da6bd7Sstefano_zampini   PetscInt               i,N;
714266da6bd7Sstefano_zampini   PetscBool              rcsr = PETSC_FALSE;
7143674ae819SStefano Zampini 
7144674ae819SStefano Zampini   PetscFunctionBegin;
71458af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
7146b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
71478e61c736SStefano Zampini     /* Reset previously computed graph */
71489566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphReset(pcbddc->mat_graph));
7149674ae819SStefano Zampini     /* Init local Graph struct */
71509566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->pmat,&N,NULL));
71519566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(pc->pmat,&map,NULL));
71529566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount));
7153674ae819SStefano Zampini 
71547a0e7b2cSstefano_zampini     if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) {
71559566063dSJacob Faibussowitsch       PetscCall(PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local));
71567a0e7b2cSstefano_zampini     }
7157575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
71582472a847SBarry 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);
71599577ea80SStefano Zampini 
7160674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
716166da6bd7Sstefano_zampini     if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) {
71624d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
71634d379d7bSStefano Zampini       PetscInt  nvtxs;
7164e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
7165674ae819SStefano Zampini 
71669566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row));
71672fffb893SStefano Zampini       if (flg_row) {
71689566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES));
7169b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
71702fffb893SStefano Zampini       }
71719566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row));
717266da6bd7Sstefano_zampini       rcsr = PETSC_TRUE;
7173674ae819SStefano Zampini     }
71749b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
71759566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
7176674ae819SStefano Zampini     }
7177674ae819SStefano Zampini 
7178ab8c8b98SStefano Zampini     if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) {
7179ab8c8b98SStefano Zampini       PetscReal    *lcoords;
7180ab8c8b98SStefano Zampini       PetscInt     n;
7181ab8c8b98SStefano Zampini       MPI_Datatype dimrealtype;
7182ab8c8b98SStefano Zampini 
71834f819b78SStefano Zampini       /* TODO: support for blocked */
718463a3b9bcSJacob 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);
71859566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(matis->A,&n,NULL));
71869566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords));
71879566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype));
71889566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_commit(&dimrealtype));
71899566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords,MPI_REPLACE));
71909566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords,MPI_REPLACE));
71919566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_free(&dimrealtype));
71929566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddc->mat_graph->coords));
7193ab8c8b98SStefano Zampini 
7194ab8c8b98SStefano Zampini       pcbddc->mat_graph->coords = lcoords;
7195ab8c8b98SStefano Zampini       pcbddc->mat_graph->cloc   = PETSC_TRUE;
7196ab8c8b98SStefano Zampini       pcbddc->mat_graph->cnloc  = n;
7197ab8c8b98SStefano Zampini     }
71982472a847SBarry 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);
7199625961bdSStefano Zampini     pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected);
7200ab8c8b98SStefano Zampini 
7201674ae819SStefano Zampini     /* Setup of Graph */
72024b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
72039566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphSetUp(pcbddc->mat_graph,pcbddc->vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local));
7204674ae819SStefano Zampini 
72054f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
72064f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
720720c3699dSStefano Zampini       PetscInt *local_subs,n,totn;
72084f1b2e48SStefano Zampini 
72099566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(matis->A,&n,NULL));
72109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n,&local_subs));
721120c3699dSStefano Zampini       for (i=0;i<n;i++) local_subs[i] = pcbddc->n_local_subs;
72124f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
72134f1b2e48SStefano Zampini         const PetscInt *idxs;
72144f1b2e48SStefano Zampini         PetscInt       nl,j;
72154f1b2e48SStefano Zampini 
72169566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(pcbddc->local_subs[i],&nl));
72179566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(pcbddc->local_subs[i],&idxs));
721871582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
72199566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(pcbddc->local_subs[i],&idxs));
72204f1b2e48SStefano Zampini       }
722120c3699dSStefano Zampini       for (i=0,totn=0;i<n;i++) totn = PetscMax(totn,local_subs[i]);
722220c3699dSStefano Zampini       pcbddc->mat_graph->n_local_subs = totn + 1;
72234f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
72244f1b2e48SStefano Zampini     }
72258af8fcf9SStefano Zampini   }
72264f1b2e48SStefano Zampini 
7227cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
7228674ae819SStefano Zampini     /* Graph's connected components analysis */
72299566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph));
723071582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
72314f819b78SStefano Zampini     pcbddc->corner_selected = pcbddc->corner_selection;
72328af8fcf9SStefano Zampini   }
723366da6bd7Sstefano_zampini   if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0;
7234674ae819SStefano Zampini   PetscFunctionReturn(0);
7235674ae819SStefano Zampini }
7236674ae819SStefano Zampini 
7237295df10fSStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[])
72389a7d3425SStefano Zampini {
7239295df10fSStefano Zampini   PetscInt       i,j,n;
72409a7d3425SStefano Zampini   PetscScalar    *alphas;
7241295df10fSStefano Zampini   PetscReal      norm,*onorms;
72429a7d3425SStefano Zampini 
72439a7d3425SStefano Zampini   PetscFunctionBegin;
7244295df10fSStefano Zampini   n = *nio;
72458c0031efSStefano Zampini   if (!n) PetscFunctionReturn(0);
72469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(n,&alphas,n,&onorms));
72479566063dSJacob Faibussowitsch   PetscCall(VecNormalize(vecs[0],&norm));
724892cccca0SStefano Zampini   if (norm < PETSC_SMALL) {
7249295df10fSStefano Zampini     onorms[0] = 0.0;
72509566063dSJacob Faibussowitsch     PetscCall(VecSet(vecs[0],0.0));
7251295df10fSStefano Zampini   } else {
7252295df10fSStefano Zampini     onorms[0] = norm;
725392cccca0SStefano Zampini   }
7254295df10fSStefano Zampini 
72558c0031efSStefano Zampini   for (i=1;i<n;i++) {
72569566063dSJacob Faibussowitsch     PetscCall(VecMDot(vecs[i],i,vecs,alphas));
72578c0031efSStefano Zampini     for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]);
72589566063dSJacob Faibussowitsch     PetscCall(VecMAXPY(vecs[i],i,alphas,vecs));
72599566063dSJacob Faibussowitsch     PetscCall(VecNormalize(vecs[i],&norm));
726092cccca0SStefano Zampini     if (norm < PETSC_SMALL) {
7261295df10fSStefano Zampini       onorms[i] = 0.0;
72629566063dSJacob Faibussowitsch       PetscCall(VecSet(vecs[i],0.0));
7263295df10fSStefano Zampini     } else {
7264295df10fSStefano Zampini       onorms[i] = norm;
726592cccca0SStefano Zampini     }
72669a7d3425SStefano Zampini   }
7267295df10fSStefano Zampini   /* push nonzero vectors at the beginning */
7268295df10fSStefano Zampini   for (i=0;i<n;i++) {
7269295df10fSStefano Zampini     if (onorms[i] == 0.0) {
7270295df10fSStefano Zampini       for (j=i+1;j<n;j++) {
7271295df10fSStefano Zampini         if (onorms[j] != 0.0) {
72729566063dSJacob Faibussowitsch           PetscCall(VecCopy(vecs[j],vecs[i]));
7273295df10fSStefano Zampini           onorms[j] = 0.0;
7274295df10fSStefano Zampini         }
7275295df10fSStefano Zampini       }
7276295df10fSStefano Zampini     }
7277295df10fSStefano Zampini   }
7278295df10fSStefano Zampini   for (i=0,*nio=0;i<n;i++) *nio += onorms[i] != 0.0 ? 1 : 0;
72799566063dSJacob Faibussowitsch   PetscCall(PetscFree2(alphas,onorms));
72809a7d3425SStefano Zampini   PetscFunctionReturn(0);
72819a7d3425SStefano Zampini }
72829a7d3425SStefano Zampini 
7283bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
7284e7931f94SStefano Zampini {
7285e432b41dSStefano Zampini   ISLocalToGlobalMapping mapping;
728657de7509SStefano Zampini   Mat                    A;
7287e7931f94SStefano Zampini   PetscInt               n_neighs,*neighs,*n_shared,**shared;
7288e7931f94SStefano Zampini   PetscMPIInt            size,rank,color;
728952e5ac9dSStefano Zampini   PetscInt               *xadj,*adjncy;
729052e5ac9dSStefano Zampini   PetscInt               *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
7291bb360cb4SStefano Zampini   PetscInt               im_active,active_procs,N,n,i,j,threshold = 2;
729257de7509SStefano Zampini   PetscInt               void_procs,*procs_candidates = NULL;
729327b6a85dSStefano Zampini   PetscInt               xadj_count,*count;
729427b6a85dSStefano Zampini   PetscBool              ismatis,use_vwgt=PETSC_FALSE;
729527b6a85dSStefano Zampini   PetscSubcomm           psubcomm;
729627b6a85dSStefano Zampini   MPI_Comm               subcomm;
7297a57a6d2fSStefano Zampini 
7298e7931f94SStefano Zampini   PetscFunctionBegin;
729957de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
73009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis));
730128b400f6SJacob 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);
730257de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
730357de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
730463a3b9bcSJacob Faibussowitsch   PetscCheck(*n_subdomains >0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %" PetscInt_FMT,*n_subdomains);
730557de7509SStefano Zampini 
730657de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
73079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
73089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank));
73099566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(mat,&A));
73109566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&n,NULL));
7311bb360cb4SStefano Zampini   im_active = !!n;
73121c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat)));
731357de7509SStefano Zampini   void_procs = size - active_procs;
731457de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
731557de7509SStefano Zampini   if (void_procs) {
731657de7509SStefano Zampini     PetscInt ncand;
731757de7509SStefano Zampini 
731857de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
73199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size,&procs_candidates));
73209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat)));
732157de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
732257de7509SStefano Zampini       if (!procs_candidates[i]) {
732357de7509SStefano Zampini         procs_candidates[ncand++] = i;
732457de7509SStefano Zampini       }
732557de7509SStefano Zampini     }
732657de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
732757de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
732857de7509SStefano Zampini   }
732957de7509SStefano Zampini 
7330bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
73319dddd249SSatish Balay      number of subdomains requested 1 -> send to rank-0 or first candidate in voids  */
73329566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&N,NULL));
7333bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
733414f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
733514f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
733614f0bfb9SStefano Zampini     else dest = rank;
733757de7509SStefano Zampini     if (im_active) {
733857de7509SStefano Zampini       issize = 1;
733957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
734014f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
734157de7509SStefano Zampini       } else {
734214f0bfb9SStefano Zampini         isidx = dest;
734357de7509SStefano Zampini       }
734457de7509SStefano Zampini     } else {
734557de7509SStefano Zampini       issize = 0;
734657de7509SStefano Zampini       isidx = -1;
734757de7509SStefano Zampini     }
7348bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
73499566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends));
73509566063dSJacob Faibussowitsch     PetscCall(PetscFree(procs_candidates));
735157de7509SStefano Zampini     PetscFunctionReturn(0);
735257de7509SStefano Zampini   }
73539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL));
73549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL));
735527b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
7356e7931f94SStefano Zampini 
7357e7931f94SStefano Zampini   /* Get info on mapping */
73589566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalToGlobalMapping(mat,&mapping,NULL));
73599566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetInfo(mapping,&n_neighs,&neighs,&n_shared,&shared));
7360e7931f94SStefano Zampini 
7361e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
73629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2,&xadj));
7363e7931f94SStefano Zampini   xadj[0] = 0;
7364e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
73659566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(xadj[1],&adjncy));
73669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(xadj[1],&adjncy_wgt));
73679566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(n,&count));
736827b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
736927b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
737027b6a85dSStefano Zampini       count[shared[i][j]] += 1;
7371e7931f94SStefano Zampini 
737227b6a85dSStefano Zampini   xadj_count = 0;
73732b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
737427b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
737527b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
7376d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
7377d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
7378d023bfaeSStefano Zampini         xadj_count++;
737927b6a85dSStefano Zampini         break;
738027b6a85dSStefano Zampini       }
7381e7931f94SStefano Zampini     }
7382e7931f94SStefano Zampini   }
7383d023bfaeSStefano Zampini   xadj[1] = xadj_count;
73849566063dSJacob Faibussowitsch   PetscCall(PetscFree(count));
73859566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreInfo(mapping,&n_neighs,&neighs,&n_shared,&shared));
73869566063dSJacob Faibussowitsch   PetscCall(PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt));
7387e7931f94SStefano Zampini 
73889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1,&ranks_send_to_idx));
7389e7931f94SStefano Zampini 
739027b6a85dSStefano Zampini   /* Restrict work on active processes only */
73919566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(im_active,&color));
739227b6a85dSStefano Zampini   if (void_procs) {
73939566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm));
73949566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetNumber(psubcomm,2)); /* 2 groups, active process and not active processes */
73959566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetTypeGeneral(psubcomm,color,rank));
739627b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
739727b6a85dSStefano Zampini   } else {
739827b6a85dSStefano Zampini     psubcomm = NULL;
739927b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
740027b6a85dSStefano Zampini   }
740127b6a85dSStefano Zampini 
740227b6a85dSStefano Zampini   v_wgt = NULL;
740327b6a85dSStefano Zampini   if (!color) {
74049566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
74059566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
74069566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy_wgt));
7407c8587f34SStefano Zampini   } else {
740852e5ac9dSStefano Zampini     Mat             subdomain_adj;
740952e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
741052e5ac9dSStefano Zampini     MatPartitioning partitioner;
741127b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
741252e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
741357de7509SStefano Zampini     PetscMPIInt     size;
7414b0c7d250SStefano Zampini     PetscBool       aggregate;
7415b0c7d250SStefano Zampini 
74169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(subcomm,&size));
741727b6a85dSStefano Zampini     if (void_procs) {
741827b6a85dSStefano Zampini       PetscInt prank = rank;
74199566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size,&oldranks));
74209566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm));
7421e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
74229566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]));
7423c8587f34SStefano Zampini       }
74249566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt));
742527b6a85dSStefano Zampini     } else {
742627b6a85dSStefano Zampini       oldranks = NULL;
742727b6a85dSStefano Zampini     }
7428b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
742927b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
7430b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
7431b0c7d250SStefano Zampini       PetscMPIInt nrank;
7432b0c7d250SStefano Zampini       PetscScalar *vals;
7433b0c7d250SStefano Zampini 
74349566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(subcomm,&nrank));
7435b0c7d250SStefano Zampini       lrows = 0;
7436b0c7d250SStefano Zampini       if (nrank<redprocs) {
7437b0c7d250SStefano Zampini         lrows = size/redprocs;
7438b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
7439b0c7d250SStefano Zampini       }
74409566063dSJacob Faibussowitsch       PetscCall(MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj));
74419566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(subdomain_adj,&rstart,&rend));
74429566063dSJacob Faibussowitsch       PetscCall(MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE));
74439566063dSJacob Faibussowitsch       PetscCall(MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE));
7444b0c7d250SStefano Zampini       row = nrank;
7445b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
7446b0c7d250SStefano Zampini       cols = adjncy;
74479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(ncols,&vals));
7448b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
74499566063dSJacob Faibussowitsch       PetscCall(MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES));
74509566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY));
74519566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY));
74529566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
74539566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
74549566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy_wgt));
74559566063dSJacob Faibussowitsch       PetscCall(PetscFree(vals));
745627b6a85dSStefano Zampini       if (use_vwgt) {
745727b6a85dSStefano Zampini         Vec               v;
745827b6a85dSStefano Zampini         const PetscScalar *array;
745927b6a85dSStefano Zampini         PetscInt          nl;
746027b6a85dSStefano Zampini 
74619566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(subdomain_adj,&v,NULL));
74629566063dSJacob Faibussowitsch         PetscCall(VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES));
74639566063dSJacob Faibussowitsch         PetscCall(VecAssemblyBegin(v));
74649566063dSJacob Faibussowitsch         PetscCall(VecAssemblyEnd(v));
74659566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(v,&nl));
74669566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(v,&array));
74679566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nl,&v_wgt));
746822db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
74699566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(v,&array));
74709566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&v));
747127b6a85dSStefano Zampini       }
7472b0c7d250SStefano Zampini     } else {
74739566063dSJacob Faibussowitsch       PetscCall(MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj));
747427b6a85dSStefano Zampini       if (use_vwgt) {
74759566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(1,&v_wgt));
7476bb360cb4SStefano Zampini         v_wgt[0] = n;
747727b6a85dSStefano Zampini       }
7478b0c7d250SStefano Zampini     }
74799566063dSJacob Faibussowitsch     /* PetscCall(MatView(subdomain_adj,0)); */
7480e7931f94SStefano Zampini 
7481e7931f94SStefano Zampini     /* Partition */
74829566063dSJacob Faibussowitsch     PetscCall(MatPartitioningCreate(subcomm,&partitioner));
7483ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH)
74849566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetType(partitioner,MATPARTITIONINGPTSCOTCH));
7485ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS)
74869566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetType(partitioner,MATPARTITIONINGPARMETIS));
7487ce64c636SStefano Zampini #else
74889566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetType(partitioner,MATPARTITIONINGAVERAGE));
7489ce64c636SStefano Zampini #endif
74909566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetAdjacency(partitioner,subdomain_adj));
749127b6a85dSStefano Zampini     if (v_wgt) {
74929566063dSJacob Faibussowitsch       PetscCall(MatPartitioningSetVertexWeights(partitioner,v_wgt));
7493c8587f34SStefano Zampini     }
749457de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
74959566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetNParts(partitioner,*n_subdomains));
74969566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetFromOptions(partitioner));
74979566063dSJacob Faibussowitsch     PetscCall(MatPartitioningApply(partitioner,&new_ranks));
74989566063dSJacob Faibussowitsch     /* PetscCall(MatPartitioningView(partitioner,0)); */
7499e7931f94SStefano Zampini 
750052e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
75019566063dSJacob Faibussowitsch     PetscCall(ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig));
75029566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&new_ranks));
75039566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices));
750457de7509SStefano Zampini     if (!aggregate) {
750557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
75066bdcaf15SBarry Smith         PetscAssert(oldranks,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
750757de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
750827b6a85dSStefano Zampini       } else if (oldranks) {
7509b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
751027b6a85dSStefano Zampini       } else {
751127b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
751257de7509SStefano Zampini       }
751328143c3dSStefano Zampini     } else {
75147fb8a5e4SKarl Rupp       PetscInt    idx = 0;
7515b0c7d250SStefano Zampini       PetscMPIInt tag;
7516b0c7d250SStefano Zampini       MPI_Request *reqs;
7517b0c7d250SStefano Zampini 
75189566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag));
75199566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(rend-rstart,&reqs));
7520b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
75219566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]));
752228143c3dSStefano Zampini       }
75239566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE));
75249566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE));
75259566063dSJacob Faibussowitsch       PetscCall(PetscFree(reqs));
752657de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
75276bdcaf15SBarry Smith         PetscAssert(oldranks,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
75287fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = procs_candidates[oldranks[idx]];
752927b6a85dSStefano Zampini       } else if (oldranks) {
75307fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = oldranks[idx];
753127b6a85dSStefano Zampini       } else {
75327fb8a5e4SKarl Rupp         ranks_send_to_idx[0] = idx;
7533e7931f94SStefano Zampini       }
753457de7509SStefano Zampini     }
75359566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices));
7536e7931f94SStefano Zampini     /* clean up */
75379566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldranks));
75389566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&new_ranks_contig));
75399566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&subdomain_adj));
75409566063dSJacob Faibussowitsch     PetscCall(MatPartitioningDestroy(&partitioner));
7541e7931f94SStefano Zampini   }
75429566063dSJacob Faibussowitsch   PetscCall(PetscSubcommDestroy(&psubcomm));
75439566063dSJacob Faibussowitsch   PetscCall(PetscFree(procs_candidates));
7544e7931f94SStefano Zampini 
7545e7931f94SStefano Zampini   /* assemble parallel IS for sends */
7546e7931f94SStefano Zampini   i = 1;
754727b6a85dSStefano Zampini   if (!color) i=0;
75489566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends));
7549e7931f94SStefano Zampini   PetscFunctionReturn(0);
7550e7931f94SStefano Zampini }
7551e7931f94SStefano Zampini 
7552e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
7553e7931f94SStefano Zampini 
75541e0482f5SStefano 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[])
7555e7931f94SStefano Zampini {
755670cf5478SStefano Zampini   Mat                    local_mat;
7557e7931f94SStefano Zampini   IS                     is_sends_internal;
75589d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
75591ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
75609d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
7561e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
7562e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
7563e7931f94SStefano Zampini   const PetscInt*        is_indices;
7564e7931f94SStefano Zampini   MatType                new_local_type;
7565e7931f94SStefano Zampini   /* buffers */
7566e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
756728143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
75689d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
75691683a169SBarry Smith   PetscScalar            *ptr_vals,*recv_buffer_vals;
75701683a169SBarry Smith   const PetscScalar      *send_buffer_vals;
75711ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
7572e7931f94SStefano Zampini   /* MPI */
757328143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
757428143c3dSStefano Zampini   PetscSubcomm           subcomm;
7575e569e4e1SStefano Zampini   PetscMPIInt            n_sends,n_recvs,size;
757628143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
757728143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
75781ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
75791ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
75801ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
7581e7931f94SStefano Zampini 
7582e7931f94SStefano Zampini   PetscFunctionBegin;
758357de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
75849566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis));
75855f80ce2aSJacob 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);
758657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
758757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
758857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
758957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
759057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
75911ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
75921ae86dd6SStefano Zampini   if (nvecs) {
759308401ef6SPierre Jolivet     PetscCheck(nvecs <= 1,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
75941ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
75951ae86dd6SStefano Zampini   }
759657de7509SStefano Zampini   /* further checks */
75979566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(mat,&local_mat));
75989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense));
75995f80ce2aSJacob Faibussowitsch   PetscCheck(isdense,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
76009566063dSJacob Faibussowitsch   PetscCall(MatGetSize(local_mat,&rows,&cols));
76015f80ce2aSJacob Faibussowitsch   PetscCheck(rows == cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
760257de7509SStefano Zampini   if (reuse && *mat_n) {
760370cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
760457de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
76059566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis));
76065f80ce2aSJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
76079566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat,&mrows,&mcols));
76089566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*mat_n,&mnrows,&mncols));
760963a3b9bcSJacob Faibussowitsch     PetscCheck(mrows == mnrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %" PetscInt_FMT " != %" PetscInt_FMT,mrows,mnrows);
761063a3b9bcSJacob Faibussowitsch     PetscCheck(mcols == mncols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %" PetscInt_FMT " != %" PetscInt_FMT,mcols,mncols);
761170cf5478SStefano Zampini   }
76129566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(local_mat,&bs));
7613064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(mat,bs,1);
761457de7509SStefano Zampini 
7615e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
7616e7931f94SStefano Zampini   if (!is_sends) {
76175f80ce2aSJacob Faibussowitsch     PetscCheck(n_subdomains,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
76189566063dSJacob Faibussowitsch     PetscCall(PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL));
7619c8587f34SStefano Zampini   } else {
76209566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)is_sends));
7621e7931f94SStefano Zampini     is_sends_internal = is_sends;
7622c8587f34SStefano Zampini   }
7623e7931f94SStefano Zampini 
7624e7931f94SStefano Zampini   /* get comm */
76259566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
7626e7931f94SStefano Zampini 
7627e7931f94SStefano Zampini   /* compute number of sends */
76289566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_sends_internal,&i));
76299566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(i,&n_sends));
7630e7931f94SStefano Zampini 
7631e7931f94SStefano Zampini   /* compute number of receives */
76329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
76339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&iflags));
76349566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(iflags,size));
76359566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_sends_internal,&is_indices));
7636e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
76379566063dSJacob Faibussowitsch   PetscCall(PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs));
76389566063dSJacob Faibussowitsch   PetscCall(PetscFree(iflags));
7639e7931f94SStefano Zampini 
764028143c3dSStefano Zampini   /* restrict comm if requested */
76410a545947SLisandro Dalcin   subcomm = NULL;
764228143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
764328143c3dSStefano Zampini   if (restrict_comm) {
7644779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
7645779c1cceSStefano Zampini 
764628143c3dSStefano Zampini     color = 0;
764753a05cb3SStefano Zampini     if (restrict_full) {
76486aad120cSJose E. Roman       if (!n_recvs) color = 1; /* processes not receiving anything will not participate in new comm (full restriction) */
764953a05cb3SStefano Zampini     } else {
76506aad120cSJose 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 */
765153a05cb3SStefano Zampini     }
76521c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm));
7653e569e4e1SStefano Zampini     subcommsize = size - subcommsize;
765428143c3dSStefano Zampini     /* check if reuse has been requested */
765557de7509SStefano Zampini     if (reuse) {
765628143c3dSStefano Zampini       if (*mat_n) {
765728143c3dSStefano Zampini         PetscMPIInt subcommsize2;
76589566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2));
76595f80ce2aSJacob Faibussowitsch         PetscCheck(subcommsize == subcommsize2,PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
766028143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
766128143c3dSStefano Zampini       } else {
766228143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
766328143c3dSStefano Zampini       }
766428143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
7665779c1cceSStefano Zampini       PetscMPIInt rank;
7666779c1cceSStefano Zampini 
76679566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm,&rank));
76689566063dSJacob Faibussowitsch       PetscCall(PetscSubcommCreate(comm,&subcomm));
76699566063dSJacob Faibussowitsch       PetscCall(PetscSubcommSetNumber(subcomm,2));
76709566063dSJacob Faibussowitsch       PetscCall(PetscSubcommSetTypeGeneral(subcomm,color,rank));
7671306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
767228143c3dSStefano Zampini     }
767328143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
767428143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
767528143c3dSStefano Zampini   } else {
767628143c3dSStefano Zampini     comm_n = comm;
767728143c3dSStefano Zampini   }
767828143c3dSStefano Zampini 
7679e7931f94SStefano Zampini   /* prepare send/receive buffers */
76809566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&ilengths_idxs));
76819566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(ilengths_idxs,size));
76829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&ilengths_vals));
76839566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(ilengths_vals,size));
768428143c3dSStefano Zampini   if (nis) {
76859566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(size,&ilengths_idxs_is));
768628143c3dSStefano Zampini   }
7687e7931f94SStefano Zampini 
768828143c3dSStefano Zampini   /* Get data from local matrices */
7689e432b41dSStefano Zampini   PetscCheck(isdense,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
7690e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
7691e7931f94SStefano Zampini     /*
7692e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
7693e7931f94SStefano Zampini        send_buffer_idxs should contain:
7694e7931f94SStefano Zampini        - MatType_PRIVATE type
7695e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
7696e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
7697e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
7698e7931f94SStefano Zampini     */
7699e432b41dSStefano Zampini   {
7700e432b41dSStefano Zampini     ISLocalToGlobalMapping mapping;
7701e432b41dSStefano Zampini 
77029566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(mat,&mapping,NULL));
77039566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(local_mat,&send_buffer_vals));
77049566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(mapping,&i));
77059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(i+2,&send_buffer_idxs));
7706e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
7707e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
77089566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(mapping,(const PetscInt**)&ptr_idxs));
77099566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&send_buffer_idxs[2],ptr_idxs,i));
77109566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping,(const PetscInt**)&ptr_idxs));
77119566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(i,&len));
7712e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
7713e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
7714e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
7715c8587f34SStefano Zampini     }
7716c8587f34SStefano Zampini   }
77179566063dSJacob Faibussowitsch   PetscCall(PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals));
771828143c3dSStefano Zampini   /* additional is (if any) */
771928143c3dSStefano Zampini   if (nis) {
772028143c3dSStefano Zampini     PetscMPIInt psum;
772128143c3dSStefano Zampini     PetscInt j;
772228143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
772328143c3dSStefano Zampini       PetscInt plen;
77249566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(isarray[j],&plen));
77259566063dSJacob Faibussowitsch       PetscCall(PetscMPIIntCast(plen,&len));
77266aad120cSJose E. Roman       psum += len+1; /* indices + length */
772728143c3dSStefano Zampini     }
77289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(psum,&send_buffer_idxs_is));
772928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
773028143c3dSStefano Zampini       PetscInt plen;
773128143c3dSStefano Zampini       const PetscInt *is_array_idxs;
77329566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(isarray[j],&plen));
773328143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
77349566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(isarray[j],&is_array_idxs));
77359566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen));
77369566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(isarray[j],&is_array_idxs));
77376aad120cSJose E. Roman       psum += plen+1; /* indices + length */
773828143c3dSStefano Zampini     }
773928143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
774028143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
774128143c3dSStefano Zampini     }
77429566063dSJacob Faibussowitsch     PetscCall(PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is));
774328143c3dSStefano Zampini   }
77449566063dSJacob Faibussowitsch   PetscCall(MatISRestoreLocalMat(mat,&local_mat));
774528143c3dSStefano Zampini 
7746e7931f94SStefano Zampini   buf_size_idxs = 0;
7747e7931f94SStefano Zampini   buf_size_vals = 0;
774828143c3dSStefano Zampini   buf_size_idxs_is = 0;
77491ae86dd6SStefano Zampini   buf_size_vecs = 0;
7750e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7751e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
7752e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
775328143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
77541ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
7755e7931f94SStefano Zampini   }
77569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_idxs,&recv_buffer_idxs));
77579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_vals,&recv_buffer_vals));
77589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is));
77599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_vecs,&recv_buffer_vecs));
7760e7931f94SStefano Zampini 
7761e7931f94SStefano Zampini   /* get new tags for clean communications */
77629566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag_idxs));
77639566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag_vals));
77649566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is));
77659566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mat,&tag_vecs));
7766e7931f94SStefano Zampini 
7767e7931f94SStefano Zampini   /* allocate for requests */
77689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_sends,&send_req_idxs));
77699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_sends,&send_req_vals));
77709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_sends,&send_req_idxs_is));
77719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_sends,&send_req_vecs));
77729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_recvs,&recv_req_idxs));
77739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_recvs,&recv_req_vals));
77749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_recvs,&recv_req_idxs_is));
77759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_recvs,&recv_req_vecs));
7776e7931f94SStefano Zampini 
7777e7931f94SStefano Zampini   /* communications */
7778e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
7779e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
778028143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
77811ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
7782e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7783e7931f94SStefano Zampini     source_dest = onodes[i];
77849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]));
77859566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]));
7786e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7787e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
778828143c3dSStefano Zampini     if (nis) {
778957de7509SStefano Zampini       source_dest = onodes_is[i];
77909566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Irecv(ptr_idxs_is,olengths_idxs_is[i],MPIU_INT,source_dest,tag_idxs_is,comm,&recv_req_idxs_is[i]));
779128143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
779228143c3dSStefano Zampini     }
77931ae86dd6SStefano Zampini     if (nvecs) {
77941ae86dd6SStefano Zampini       source_dest = onodes[i];
77959566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]));
77961ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
77971ae86dd6SStefano Zampini     }
7798e7931f94SStefano Zampini   }
7799e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
78009566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(is_indices[i],&source_dest));
78019566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]));
78029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Isend((PetscScalar*)send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]));
780328143c3dSStefano Zampini     if (nis) {
78049566063dSJacob 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]));
780528143c3dSStefano Zampini     }
78061ae86dd6SStefano Zampini     if (nvecs) {
78079566063dSJacob Faibussowitsch       PetscCall(VecGetArray(nnsp_vec[0],&send_buffer_vecs));
78089566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend(send_buffer_vecs,ilengths_idxs[source_dest]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&send_req_vecs[i]));
78091ae86dd6SStefano Zampini     }
7810e7931f94SStefano Zampini   }
78119566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_sends_internal,&is_indices));
78129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_sends_internal));
7813e7931f94SStefano Zampini 
7814e7931f94SStefano Zampini   /* assemble new l2g map */
78159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE));
7816e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
78179d30be91SStefano Zampini   new_local_rows = 0;
7818e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
78199d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7820e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7821e7931f94SStefano Zampini   }
78229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(new_local_rows,&l2gmap_indices));
7823e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
78249d30be91SStefano Zampini   new_local_rows = 0;
7825e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
78269566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,*(ptr_idxs+1)));
78279d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
7828e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7829e7931f94SStefano Zampini   }
78309566063dSJacob Faibussowitsch   PetscCall(PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices));
78319566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap));
78329566063dSJacob Faibussowitsch   PetscCall(PetscFree(l2gmap_indices));
7833e7931f94SStefano Zampini 
7834e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
7835e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
7836e7931f94SStefano 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) */
7837e7931f94SStefano Zampini   if (n_recvs) {
783828143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
7839e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
7840e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
7841e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
7842e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
7843e7931f94SStefano Zampini         break;
7844e7931f94SStefano Zampini       }
7845e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
7846e7931f94SStefano Zampini     }
7847e7931f94SStefano Zampini     switch (new_local_type_private) {
784828143c3dSStefano Zampini       case MATDENSE_PRIVATE:
7849e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7850e7931f94SStefano Zampini         bs = 1;
7851e7931f94SStefano Zampini         break;
7852e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
7853e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
7854e7931f94SStefano Zampini         bs = 1;
7855e7931f94SStefano Zampini         break;
7856e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
7857e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
7858e7931f94SStefano Zampini         break;
7859e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
7860e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
7861e7931f94SStefano Zampini         break;
7862e7931f94SStefano Zampini       default:
786398921bdaSJacob Faibussowitsch         SETERRQ(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME);
7864e7931f94SStefano Zampini     }
7865ed8ed4edSstefano_zampini   } else { /* by default, new_local_type is seqaij */
7866ed8ed4edSstefano_zampini     new_local_type = MATSEQAIJ;
786728143c3dSStefano Zampini     bs = 1;
7868e7931f94SStefano Zampini   }
7869e7931f94SStefano Zampini 
787070cf5478SStefano Zampini   /* create MATIS object if needed */
787157de7509SStefano Zampini   if (!reuse) {
78729566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat,&rows,&cols));
78739566063dSJacob Faibussowitsch     PetscCall(MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,l2gmap,mat_n));
787470cf5478SStefano Zampini   } else {
787570cf5478SStefano Zampini     /* it also destroys the local matrices */
787657de7509SStefano Zampini     if (*mat_n) {
78779566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap));
787857de7509SStefano Zampini     } else { /* this is a fake object */
78799566063dSJacob Faibussowitsch       PetscCall(MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,l2gmap,mat_n));
788057de7509SStefano Zampini     }
788170cf5478SStefano Zampini   }
78829566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(*mat_n,&local_mat));
78839566063dSJacob Faibussowitsch   PetscCall(MatSetType(local_mat,new_local_type));
78849d30be91SStefano Zampini 
78859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE));
78869d30be91SStefano Zampini 
78879d30be91SStefano Zampini   /* Global to local map of received indices */
78889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local)); /* needed for values insertion */
78899566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local));
78909566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap));
78919d30be91SStefano Zampini 
78929d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
78939d30be91SStefano Zampini   buf_size_idxs = 0;
78949d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
78959d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
78969d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
78979d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
78989d30be91SStefano Zampini   }
78999566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_idxs));
79009d30be91SStefano Zampini 
79019d30be91SStefano Zampini   /* set preallocation */
79029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense));
79039d30be91SStefano Zampini   if (!newisdense) {
79040a545947SLisandro Dalcin     PetscInt *new_local_nnz=NULL;
79059d30be91SStefano Zampini 
79069d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
79079d30be91SStefano Zampini     if (n_recvs) {
79089566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(new_local_rows,&new_local_nnz));
79099d30be91SStefano Zampini     }
79109d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
79119d30be91SStefano Zampini       PetscInt j;
79129d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
79139d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
79149d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
79159d30be91SStefano Zampini         }
79169d30be91SStefano Zampini       } else {
79179d30be91SStefano Zampini         /* TODO */
79189d30be91SStefano Zampini       }
79199d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
79209d30be91SStefano Zampini     }
79219d30be91SStefano Zampini     if (new_local_nnz) {
79229d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
79239566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz));
79249d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
79259566063dSJacob Faibussowitsch       PetscCall(MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz));
79269d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
79279566063dSJacob Faibussowitsch       PetscCall(MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz));
79289d30be91SStefano Zampini     } else {
79299566063dSJacob Faibussowitsch       PetscCall(MatSetUp(local_mat));
79309d30be91SStefano Zampini     }
79319566063dSJacob Faibussowitsch     PetscCall(PetscFree(new_local_nnz));
79329d30be91SStefano Zampini   } else {
79339566063dSJacob Faibussowitsch     PetscCall(MatSetUp(local_mat));
79349d30be91SStefano Zampini   }
7935e7931f94SStefano Zampini 
7936e7931f94SStefano Zampini   /* set values */
7937e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
79389d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7939e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7940e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
79419566063dSJacob Faibussowitsch       PetscCall(MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE));
79429566063dSJacob Faibussowitsch       PetscCall(MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES));
79439566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY));
79449566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY));
79459566063dSJacob Faibussowitsch       PetscCall(MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE));
794628143c3dSStefano Zampini     } else {
794728143c3dSStefano Zampini       /* TODO */
7948e7931f94SStefano Zampini     }
7949e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7950e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7951e7931f94SStefano Zampini   }
79529566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY));
79539566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY));
79549566063dSJacob Faibussowitsch   PetscCall(MatISRestoreLocalMat(*mat_n,&local_mat));
79559566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY));
79569566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY));
79579566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_vals));
7958e7931f94SStefano Zampini 
7959dfd14d43SStefano Zampini #if 0
796028143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7961e7931f94SStefano Zampini     Vec       lvec,rvec;
7962e7931f94SStefano Zampini     PetscReal infty_error;
7963e7931f94SStefano Zampini 
79649566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(mat,&rvec,&lvec));
79659566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(rvec,NULL));
79669566063dSJacob Faibussowitsch     PetscCall(MatMult(mat,rvec,lvec));
79679566063dSJacob Faibussowitsch     PetscCall(VecScale(lvec,-1.0));
79689566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(*mat_n,rvec,lvec,lvec));
79699566063dSJacob Faibussowitsch     PetscCall(VecNorm(lvec,NORM_INFINITY,&infty_error));
79709566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error));
79719566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rvec));
79729566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&lvec));
7973e7931f94SStefano Zampini   }
797428143c3dSStefano Zampini #endif
7975e7931f94SStefano Zampini 
797628143c3dSStefano Zampini   /* assemble new additional is (if any) */
797728143c3dSStefano Zampini   if (nis) {
797828143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
797928143c3dSStefano Zampini 
79809566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE));
79819566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nis,&count_is));
798228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
798328143c3dSStefano Zampini     psum = 0;
798428143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
798528143c3dSStefano Zampini       for (j=0;j<nis;j++) {
798628143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
798728143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
798828143c3dSStefano Zampini         psum += plen;
798928143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
799028143c3dSStefano Zampini       }
799128143c3dSStefano Zampini     }
79929566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nis,&temp_idxs));
79939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(psum,&temp_idxs[0]));
799428143c3dSStefano Zampini     for (i=1;i<nis;i++) {
799528143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
799628143c3dSStefano Zampini     }
79979566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(count_is,nis));
799828143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
799928143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
800028143c3dSStefano Zampini       for (j=0;j<nis;j++) {
800128143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
80029566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen));
800328143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
800428143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
800528143c3dSStefano Zampini       }
800628143c3dSStefano Zampini     }
800728143c3dSStefano Zampini     for (i=0;i<nis;i++) {
80089566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isarray[i]));
80099566063dSJacob Faibussowitsch       PetscCall(PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]));
80109566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]));
801128143c3dSStefano Zampini     }
80129566063dSJacob Faibussowitsch     PetscCall(PetscFree(count_is));
80139566063dSJacob Faibussowitsch     PetscCall(PetscFree(temp_idxs[0]));
80149566063dSJacob Faibussowitsch     PetscCall(PetscFree(temp_idxs));
801528143c3dSStefano Zampini   }
8016e7931f94SStefano Zampini   /* free workspace */
80179566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_idxs_is));
80189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE));
80199566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_buffer_idxs));
80209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE));
8021e7931f94SStefano Zampini   if (isdense) {
80229566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(mat,&local_mat));
80239566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(local_mat,&send_buffer_vals));
80249566063dSJacob Faibussowitsch     PetscCall(MatISRestoreLocalMat(mat,&local_mat));
8025e7931f94SStefano Zampini   } else {
80269566063dSJacob Faibussowitsch     /* PetscCall(PetscFree(send_buffer_vals)); */
8027e7931f94SStefano Zampini   }
802828143c3dSStefano Zampini   if (nis) {
80299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE));
80309566063dSJacob Faibussowitsch     PetscCall(PetscFree(send_buffer_idxs_is));
803128143c3dSStefano Zampini   }
80321ae86dd6SStefano Zampini 
80331ae86dd6SStefano Zampini   if (nvecs) {
80349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE));
80359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE));
80369566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(nnsp_vec[0],&send_buffer_vecs));
80379566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nnsp_vec[0]));
80389566063dSJacob Faibussowitsch     PetscCall(VecCreate(comm_n,&nnsp_vec[0]));
80399566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE));
80409566063dSJacob Faibussowitsch     PetscCall(VecSetType(nnsp_vec[0],VECSTANDARD));
80411ae86dd6SStefano Zampini     /* set values */
80421ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
80431ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
80449566063dSJacob Faibussowitsch     PetscCall(VecGetArray(nnsp_vec[0],&send_buffer_vecs));
80451ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
80461ae86dd6SStefano Zampini       PetscInt j;
80471ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
80481ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
80491ae86dd6SStefano Zampini       }
80501ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
80511ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
80521ae86dd6SStefano Zampini     }
80539566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(nnsp_vec[0],&send_buffer_vecs));
80549566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(nnsp_vec[0]));
80559566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(nnsp_vec[0]));
80561ae86dd6SStefano Zampini   }
80571ae86dd6SStefano Zampini 
80589566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_vecs));
80599566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_buffer_idxs_local));
80609566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_req_idxs));
80619566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_req_vals));
80629566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_req_vecs));
80639566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_req_idxs_is));
80649566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_req_idxs));
80659566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_req_vals));
80669566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_req_vecs));
80679566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_req_idxs_is));
80689566063dSJacob Faibussowitsch   PetscCall(PetscFree(ilengths_vals));
80699566063dSJacob Faibussowitsch   PetscCall(PetscFree(ilengths_idxs));
80709566063dSJacob Faibussowitsch   PetscCall(PetscFree(olengths_vals));
80719566063dSJacob Faibussowitsch   PetscCall(PetscFree(olengths_idxs));
80729566063dSJacob Faibussowitsch   PetscCall(PetscFree(onodes));
807328143c3dSStefano Zampini   if (nis) {
80749566063dSJacob Faibussowitsch     PetscCall(PetscFree(ilengths_idxs_is));
80759566063dSJacob Faibussowitsch     PetscCall(PetscFree(olengths_idxs_is));
80769566063dSJacob Faibussowitsch     PetscCall(PetscFree(onodes_is));
807728143c3dSStefano Zampini   }
80789566063dSJacob Faibussowitsch   PetscCall(PetscSubcommDestroy(&subcomm));
80796aad120cSJose E. Roman   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not participate */
80809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(mat_n));
808128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
80829566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isarray[i]));
808328143c3dSStefano Zampini     }
80841ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
80859566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&nnsp_vec[0]));
80861ae86dd6SStefano Zampini     }
808753a05cb3SStefano Zampini     *mat_n = NULL;
808828143c3dSStefano Zampini   }
8089e7931f94SStefano Zampini   PetscFunctionReturn(0);
8090e7931f94SStefano Zampini }
8091a57a6d2fSStefano Zampini 
809212edc857SStefano Zampini /* temporary hack into ksp private data structure */
8093af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
809412edc857SStefano Zampini 
8095c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
8096c8587f34SStefano Zampini {
8097c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
8098c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
809920a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
81001ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
81011e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
81029881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
810320a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
81044f819b78SStefano Zampini   IS                     coarse_is,*isarray,corners;
81056e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
810630368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
8107e569e4e1SStefano Zampini   PetscInt               coarse_eqs_per_proc;
8108f9eb5b7dSStefano Zampini   PC                     pc_temp;
8109c8587f34SStefano Zampini   PCType                 coarse_pc_type;
8110c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
8111f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
81127274672aSStefano Zampini   PetscBool              coarse_reuse;
81131e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
811468457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
811522bc73bbSStefano Zampini   PetscScalar            *array;
811657de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
811757de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
8118e569e4e1SStefano Zampini   PetscMPIInt            size;
8119fdc09c96SStefano Zampini 
8120c8587f34SStefano Zampini   PetscFunctionBegin;
81219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0));
8122c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
812368457ee5SStefano 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 */
8124fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
81255a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
81267de4f681Sstefano_zampini 
81277de4f681Sstefano_zampini     pcbddc->new_primal_space = PETSC_TRUE;
8128fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
81299566063dSJacob Faibussowitsch     PetscCall(PetscFree(pcbddc->global_primal_indices));
81309566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices));
8131f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
8132fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
813351bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
813451bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
81359566063dSJacob Faibussowitsch         PetscCall(KSPReset(pcbddc->coarse_ksp));
8136fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
8137fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
8138fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
8139f4ddd8eeSStefano Zampini       }
8140fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
8141fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
8142f4ddd8eeSStefano Zampini     }
814370cf5478SStefano Zampini     /* reset any subassembling information */
814457de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
81459566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pcbddc->coarse_subassembling));
814657de7509SStefano Zampini     }
81476e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
8148fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
8149f4ddd8eeSStefano Zampini   }
815057de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
81519566063dSJacob Faibussowitsch     PetscCall(KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL));
81529566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarse_mat));
815357de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
815418a45a71SStefano Zampini   } else {
815557de7509SStefano Zampini     coarse_mat = NULL;
815657de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
81576e683305SStefano Zampini   }
8158e7931f94SStefano Zampini 
8159abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
81609566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is));
81619566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg));
8162abbbba34SStefano Zampini 
8163abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
81649566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_submat_dense));
81659566063dSJacob 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));
81669566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense));
81679566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY));
81689566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY));
81699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarse_submat_dense));
8170abbbba34SStefano Zampini 
817157de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
817257de7509SStefano Zampini   im_active = !!(pcis->n);
81731c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc)));
817457de7509SStefano Zampini 
817514f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
817628d58a37SPierre Jolivet   /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */
817757de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
81789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
817957de7509SStefano Zampini   coarse_mat_is        = NULL;
818057de7509SStefano Zampini   multilevel_allowed   = PETSC_FALSE;
818157de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
8182e569e4e1SStefano Zampini   coarse_eqs_per_proc  = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
8183ce64c636SStefano Zampini   if (coarse_eqs_per_proc < 0) coarse_eqs_per_proc = pcbddc->coarse_size;
818457de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
8185e569e4e1SStefano Zampini   if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE;
818657de7509SStefano Zampini   if (multilevel_requested) {
818757de7509SStefano Zampini     ncoarse    = active_procs/pcbddc->coarsening_ratio;
818857de7509SStefano Zampini     restr      = PETSC_FALSE;
818957de7509SStefano Zampini     full_restr = PETSC_FALSE;
819057de7509SStefano Zampini   } else {
8191e569e4e1SStefano Zampini     ncoarse    = pcbddc->coarse_size/coarse_eqs_per_proc + !!(pcbddc->coarse_size%coarse_eqs_per_proc);
819257de7509SStefano Zampini     restr      = PETSC_TRUE;
819357de7509SStefano Zampini     full_restr = PETSC_TRUE;
819457de7509SStefano Zampini   }
8195e569e4e1SStefano Zampini   if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
819657de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
819757de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
8198a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
8199bb360cb4SStefano Zampini       if (multilevel_requested) {
82009566063dSJacob Faibussowitsch         PetscCall(PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void));
8201bb360cb4SStefano Zampini       } else {
82029566063dSJacob Faibussowitsch         PetscCall(PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void));
8203bb360cb4SStefano Zampini       }
8204a198735bSStefano Zampini     } else {
82057de4f681Sstefano_zampini       PetscMPIInt rank;
820628d58a37SPierre Jolivet 
82079566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
8208e569e4e1SStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
82099566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling));
8210a198735bSStefano Zampini     }
821157de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
821257de7509SStefano Zampini     PetscInt    psum;
821357de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
821457de7509SStefano Zampini     else psum = 0;
82151c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc)));
8216075e25bcSStefano Zampini     have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE;
821757de7509SStefano Zampini   }
821857de7509SStefano Zampini   /* determine if we can go multilevel */
821957de7509SStefano Zampini   if (multilevel_requested) {
822057de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
822157de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
822257de7509SStefano Zampini   }
822357de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
822457de7509SStefano Zampini 
8225e4d548c7SStefano Zampini   /* dump subassembling pattern */
8226e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
82279566063dSJacob Faibussowitsch     PetscCall(ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer));
8228e4d548c7SStefano Zampini   }
82296e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
82301e0482f5SStefano Zampini   nedcfield = -1;
82314f819b78SStefano Zampini   corners = NULL;
82328966356dSPierre Jolivet   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */
82336e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
82346e683305SStefano Zampini     const PetscInt         *idxs;
82356e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
82366e683305SStefano Zampini 
82376e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
82389566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap));
82396e683305SStefano Zampini     /* allocate space for temporary storage */
82409566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcbddc->local_primal_size,&tidxs));
82419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcbddc->local_primal_size,&tidxs2));
82426e683305SStefano Zampini     /* allocate for IS array */
82436e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
82441e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
82451e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
82461e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
82471e0482f5SStefano Zampini       } else {
82481e0482f5SStefano Zampini         nedcfield = 0;
824963a3b9bcSJacob Faibussowitsch         PetscCheck(!nisdofs,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%" PetscInt_FMT ")",nisdofs);
82501e0482f5SStefano Zampini         nisdofs = 1;
82511e0482f5SStefano Zampini       }
82521e0482f5SStefano Zampini     }
82536e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
825427b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
825530368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
82569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nis,&isarray));
82576e683305SStefano Zampini     /* dofs splitting */
82586e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
82599566063dSJacob Faibussowitsch       /* PetscCall(ISView(pcbddc->ISForDofsLocal[i],0)); */
82601e0482f5SStefano Zampini       if (nedcfield != i) {
82619566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize));
82629566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs));
82639566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs));
82649566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs));
82651e0482f5SStefano Zampini       } else {
82669566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(pcbddc->nedclocal,&tsize));
82679566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(pcbddc->nedclocal,&idxs));
82689566063dSJacob Faibussowitsch         PetscCall(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs));
826963a3b9bcSJacob Faibussowitsch         PetscCheck(tsize == nout,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %" PetscInt_FMT " != %" PetscInt_FMT,tsize,nout);
82709566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(pcbddc->nedclocal,&idxs));
82711e0482f5SStefano Zampini       }
82729566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2));
82739566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]));
82749566063dSJacob Faibussowitsch       /* PetscCall(ISView(isarray[i],0)); */
82756e683305SStefano Zampini     }
82766e683305SStefano Zampini     /* neumann boundaries */
82776e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
82789566063dSJacob Faibussowitsch       /* PetscCall(ISView(pcbddc->NeumannBoundariesLocal,0)); */
82799566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize));
82809566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs));
82819566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs));
82829566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs));
82839566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2));
82849566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]));
82859566063dSJacob Faibussowitsch       /* PetscCall(ISView(isarray[nisdofs],0)); */
82866e683305SStefano Zampini     }
82874f819b78SStefano Zampini     /* coordinates */
82884f819b78SStefano Zampini     if (pcbddc->corner_selected) {
82899566063dSJacob Faibussowitsch       PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners));
82909566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(corners,&tsize));
82919566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(corners,&idxs));
82929566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs));
829363a3b9bcSJacob Faibussowitsch       PetscCheck(tsize == nout,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping corners! %" PetscInt_FMT " != %" PetscInt_FMT,tsize,nout);
82949566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(corners,&idxs));
82959566063dSJacob Faibussowitsch       PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners));
82969566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2));
82979566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&corners));
82984f819b78SStefano Zampini     }
82999566063dSJacob Faibussowitsch     PetscCall(PetscFree(tidxs));
83009566063dSJacob Faibussowitsch     PetscCall(PetscFree(tidxs2));
83019566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&tmap));
83026e683305SStefano Zampini   } else {
83036e683305SStefano Zampini     nis = 0;
83046e683305SStefano Zampini     nisdofs = 0;
83056e683305SStefano Zampini     nisneu = 0;
830630368db7SStefano Zampini     nisvert = 0;
83076e683305SStefano Zampini     isarray = NULL;
83086e683305SStefano Zampini   }
83096e683305SStefano Zampini   /* destroy no longer needed map */
83109566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&coarse_islg));
83116e683305SStefano Zampini 
831257de7509SStefano Zampini   /* subassemble */
831357de7509SStefano Zampini   if (multilevel_allowed) {
83141ae86dd6SStefano Zampini     Vec       vp[1];
83151ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
831657de7509SStefano Zampini     PetscBool reuse,reuser;
83171ae86dd6SStefano Zampini 
831857de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
831957de7509SStefano Zampini     else reuse = PETSC_FALSE;
83201c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
83211ae86dd6SStefano Zampini     vp[0] = NULL;
83221ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
83239566063dSJacob Faibussowitsch       PetscCall(VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]));
83249566063dSJacob Faibussowitsch       PetscCall(VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE));
83259566063dSJacob Faibussowitsch       PetscCall(VecSetType(vp[0],VECSTANDARD));
83261ae86dd6SStefano Zampini       nvecs = 1;
83271ae86dd6SStefano Zampini 
83281ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
8329a198735bSStefano Zampini         Mat      B,loc_divudotp;
83301ae86dd6SStefano Zampini         Vec      v,p;
83311ae86dd6SStefano Zampini         IS       dummy;
83321ae86dd6SStefano Zampini         PetscInt np;
83331ae86dd6SStefano Zampini 
83349566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp));
83359566063dSJacob Faibussowitsch         PetscCall(MatGetSize(loc_divudotp,&np,NULL));
83369566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy));
83379566063dSJacob Faibussowitsch         PetscCall(MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B));
83389566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(B,&v,&p));
83399566063dSJacob Faibussowitsch         PetscCall(VecSet(p,1.));
83409566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(B,p,v));
83419566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&p));
83429566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&B));
83439566063dSJacob Faibussowitsch         PetscCall(VecGetArray(vp[0],&array));
83449566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(pcbddc->vec1_P,array));
83459566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P));
83469566063dSJacob Faibussowitsch         PetscCall(VecResetArray(pcbddc->vec1_P));
83479566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(vp[0],&array));
83489566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&dummy));
83499566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&v));
835074e2c79eSStefano Zampini       }
83511ae86dd6SStefano Zampini     }
83521ae86dd6SStefano Zampini     if (reuser) {
83539566063dSJacob Faibussowitsch       PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp));
835474e2c79eSStefano Zampini     } else {
83559566063dSJacob Faibussowitsch       PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray,nvecs,vp));
83561ae86dd6SStefano Zampini     }
83571ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
83581683a169SBarry Smith       PetscScalar       *arraym;
83591683a169SBarry Smith       const PetscScalar *arrayv;
83601ae86dd6SStefano Zampini       PetscInt          nl;
83619566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(vp[0],&nl));
83629566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp));
83639566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(coarsedivudotp,&arraym));
83649566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(vp[0],&arrayv));
83659566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(arraym,arrayv,nl));
83669566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(vp[0],&arrayv));
83679566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(coarsedivudotp,&arraym));
83689566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&vp[0]));
8369a198735bSStefano Zampini     } else {
83709566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp));
83711ae86dd6SStefano Zampini     }
83721ae86dd6SStefano Zampini   } else {
83739566063dSJacob Faibussowitsch     PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,0,NULL,0,NULL));
83746e683305SStefano Zampini   }
837557de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
837657de7509SStefano Zampini     if (!multilevel_allowed) {
83779566063dSJacob Faibussowitsch       PetscCall(MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat));
83786e683305SStefano Zampini     } else {
837957de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
838057de7509SStefano Zampini       if (coarse_mat_is) {
838128b400f6SJacob Faibussowitsch         PetscCheck(!coarse_mat,PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
83829566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)coarse_mat_is));
838357de7509SStefano Zampini         coarse_mat = coarse_mat_is;
838457de7509SStefano Zampini       }
8385779c1cceSStefano Zampini     }
8386779c1cceSStefano Zampini   }
83879566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&t_coarse_mat_is));
83889566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarse_mat_is));
83896e683305SStefano Zampini 
83906e683305SStefano Zampini   /* create local to global scatters for coarse problem */
839168457ee5SStefano Zampini   if (compute_vecs) {
83926e683305SStefano Zampini     PetscInt lrows;
83939566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->coarse_vec));
839457de7509SStefano Zampini     if (coarse_mat) {
83959566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(coarse_mat,&lrows,NULL));
83966e683305SStefano Zampini     } else {
83976e683305SStefano Zampini       lrows = 0;
83986e683305SStefano Zampini     }
83999566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec));
84009566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE));
84019566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcbddc->coarse_vec,coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD));
84029566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob));
84039566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob));
84046e683305SStefano Zampini   }
84059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&coarse_is));
8406c8587f34SStefano Zampini 
8407f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
8408f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
8409f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
8410f9eb5b7dSStefano Zampini     coarse_pc_type  = PCBDDC;
8411f9eb5b7dSStefano Zampini   } else {
8412f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
8413f9eb5b7dSStefano Zampini     coarse_pc_type  = PCREDUNDANT;
8414c8587f34SStefano Zampini   }
8415c8587f34SStefano Zampini 
84166e683305SStefano Zampini   /* print some info if requested */
84176e683305SStefano Zampini   if (pcbddc->dbg_flag) {
84186e683305SStefano Zampini     if (!multilevel_allowed) {
84199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
84206e683305SStefano Zampini       if (multilevel_requested) {
842163a3b9bcSJacob 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));
84226e683305SStefano Zampini       } else if (pcbddc->max_levels) {
842363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%" PetscInt_FMT ")\n",pcbddc->max_levels));
84246e683305SStefano Zampini       }
84259566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
84266e683305SStefano Zampini     }
84276e683305SStefano Zampini   }
84286e683305SStefano Zampini 
84291e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
84301e0482f5SStefano Zampini   coarseG = NULL;
84311e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
84321e0482f5SStefano Zampini     MPI_Comm ccomm;
84331e0482f5SStefano Zampini     if (coarse_mat) {
84341e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
84351e0482f5SStefano Zampini     } else {
84361e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
84371e0482f5SStefano Zampini     }
84389566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG));
84391e0482f5SStefano Zampini   }
84401e0482f5SStefano Zampini 
8441f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
844257de7509SStefano Zampini   if (coarse_mat) {
844328d58a37SPierre Jolivet     PetscBool   isredundant,isbddc,force,valid;
84446a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
84457274672aSStefano Zampini 
84466e683305SStefano Zampini     if (pcbddc->dbg_flag) {
844757de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
84489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level));
84496e683305SStefano Zampini     }
8450f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
8451312be037SStefano Zampini       char   prefix[256],str_level[16];
8452e604994aSStefano Zampini       size_t len;
84531e0482f5SStefano Zampini 
84549566063dSJacob Faibussowitsch       PetscCall(KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp));
84559566063dSJacob Faibussowitsch       PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure));
84569566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1));
84579566063dSJacob Faibussowitsch       PetscCall(KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1));
84589566063dSJacob Faibussowitsch       PetscCall(KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat));
84599566063dSJacob Faibussowitsch       PetscCall(KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type));
84609566063dSJacob Faibussowitsch       PetscCall(KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE));
84619566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&pc_temp));
84621e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
84639566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,coarse_pc_type));
8464e604994aSStefano Zampini       /* prefix */
84659566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(prefix,""));
84669566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(str_level,""));
8467e604994aSStefano Zampini       if (!pcbddc->current_level) {
84689566063dSJacob Faibussowitsch         PetscCall(PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix)));
84699566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix)));
8470c8587f34SStefano Zampini       } else {
84719566063dSJacob Faibussowitsch         PetscCall(PetscStrlen(((PetscObject)pc)->prefix,&len));
8472312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
8473312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
8474a126751eSBarry Smith         /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */
84759566063dSJacob Faibussowitsch         PetscCall(PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1));
84769566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level)));
84779566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(prefix,str_level,sizeof(prefix)));
8478e604994aSStefano Zampini       }
84799566063dSJacob Faibussowitsch       PetscCall(KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix));
84803e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
84819566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetLevel(pc_temp,pcbddc->current_level+1));
84829566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio));
84839566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetLevels(pc_temp,pcbddc->max_levels));
8484f9eb5b7dSStefano Zampini       /* allow user customization */
84859566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(pcbddc->coarse_ksp));
8486e569e4e1SStefano Zampini       /* get some info after set from options */
84879566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&pc_temp));
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,""));
84929566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc));
849328d58a37SPierre Jolivet       if (multilevel_allowed && !force && !valid) {
8494e569e4e1SStefano Zampini         isbddc = PETSC_TRUE;
84959566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc_temp,PCBDDC));
84969566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetLevel(pc_temp,pcbddc->current_level+1));
84979566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio));
84989566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetLevels(pc_temp,pcbddc->max_levels));
84994f819b78SStefano Zampini         if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */
8500d0609cedSBarry Smith           PetscObjectOptionsBegin((PetscObject)pc_temp);
85019566063dSJacob Faibussowitsch           PetscCall((*pc_temp->ops->setfromoptions)(PetscOptionsObject,pc_temp));
85029566063dSJacob Faibussowitsch           PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pc_temp));
8503d0609cedSBarry Smith           PetscOptionsEnd();
85044f819b78SStefano Zampini           pc_temp->setfromoptionscalled++;
85054f819b78SStefano Zampini         }
8506e569e4e1SStefano Zampini       }
85073e3c6dadSStefano Zampini     }
85083e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
85099566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcbddc->coarse_ksp,&pc_temp));
85103e3c6dadSStefano Zampini     if (nisdofs) {
85119566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray));
85123e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
85139566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&isarray[i]));
85143e3c6dadSStefano Zampini       }
85153e3c6dadSStefano Zampini     }
85163e3c6dadSStefano Zampini     if (nisneu) {
85179566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]));
85189566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isarray[nisdofs]));
8519312be037SStefano Zampini     }
852030368db7SStefano Zampini     if (nisvert) {
85219566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]));
85229566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isarray[nis-1]));
852330368db7SStefano Zampini     }
85241e0482f5SStefano Zampini     if (coarseG) {
85259566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE));
85261e0482f5SStefano Zampini     }
8527f9eb5b7dSStefano Zampini 
8528f9eb5b7dSStefano Zampini     /* get some info after set from options */
85299566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc));
85304f819b78SStefano Zampini 
8531b76f3995Sstefano_zampini     /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */
8532b76f3995Sstefano_zampini     if (isbddc && !multilevel_allowed) {
85339566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,coarse_pc_type));
8534f9eb5b7dSStefano Zampini     }
853528d58a37SPierre Jolivet     /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */
853628d58a37SPierre Jolivet     force = PETSC_FALSE;
85379566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL));
85389566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,""));
853928d58a37SPierre Jolivet     if (multilevel_requested && multilevel_allowed && !valid && !force) {
85409566063dSJacob Faibussowitsch       PetscCall(PCSetType(pc_temp,PCBDDC));
8541b76f3995Sstefano_zampini     }
85429566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant));
85434f3a063dSStefano Zampini     if (isredundant) {
85444f3a063dSStefano Zampini       KSP inner_ksp;
85454f3a063dSStefano Zampini       PC  inner_pc;
85469326c5c6Sstefano_zampini 
85479566063dSJacob Faibussowitsch       PetscCall(PCRedundantGetKSP(pc_temp,&inner_ksp));
85489566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(inner_ksp,&inner_pc));
85494f3a063dSStefano Zampini     }
8550f9eb5b7dSStefano Zampini 
855157de7509SStefano Zampini     /* parameters which miss an API */
85529566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc));
855357de7509SStefano Zampini     if (isbddc) {
8554720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
85557274672aSStefano Zampini 
8556720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
855757de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
8558e569e4e1SStefano Zampini       pcbddc_coarse->coarse_eqs_limit    = pcbddc->coarse_eqs_limit;
855927b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
856027b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
8561a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
8562a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
8563a198735bSStefano Zampini         IS                     row,col;
8564a198735bSStefano Zampini         const PetscInt         *gidxs;
8565a198735bSStefano Zampini         PetscInt               n,st,M,N;
8566a198735bSStefano Zampini 
85679566063dSJacob Faibussowitsch         PetscCall(MatGetSize(coarsedivudotp,&n,NULL));
85689566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat)));
8569a198735bSStefano Zampini         st   = st-n;
85709566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row));
85719566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL));
85729566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(l2gmap,&n));
85739566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs));
85749566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col));
85759566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs));
85769566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingCreateIS(row,&rl2g));
85779566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingCreateIS(col,&cl2g));
85789566063dSJacob Faibussowitsch         PetscCall(ISGetSize(row,&M));
85799566063dSJacob Faibussowitsch         PetscCall(MatGetSize(coarse_mat,&N,NULL));
85809566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&row));
85819566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&col));
85829566063dSJacob Faibussowitsch         PetscCall(MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is));
85839566063dSJacob Faibussowitsch         PetscCall(MatSetType(coarsedivudotp_is,MATIS));
85849566063dSJacob Faibussowitsch         PetscCall(MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N));
85859566063dSJacob Faibussowitsch         PetscCall(MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g));
85869566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
85879566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
85889566063dSJacob Faibussowitsch         PetscCall(MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp));
85899566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&coarsedivudotp));
85909566063dSJacob Faibussowitsch         PetscCall(PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL));
85919566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&coarsedivudotp_is));
8592720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
8593bd2a564bSStefano Zampini         if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
8594720d30f9SStefano Zampini       }
8595d4d8cf7bSStefano Zampini     }
85969881197aSStefano Zampini 
85973301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
85989566063dSJacob Faibussowitsch     PetscCall(MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE));
85993301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
86009566063dSJacob Faibussowitsch       PetscCall(MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric));
86013301b35fSStefano Zampini     }
86023301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
86039566063dSJacob Faibussowitsch       PetscCall(MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian));
86043301b35fSStefano Zampini     }
86053301b35fSStefano Zampini     if (pc->pmat->spd_set) {
86069566063dSJacob Faibussowitsch       PetscCall(MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd));
86073301b35fSStefano Zampini     }
860827b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
86099566063dSJacob Faibussowitsch       PetscCall(MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE));
861027b6a85dSStefano Zampini     }
86116e683305SStefano Zampini     /* set operators */
86129566063dSJacob Faibussowitsch     PetscCall(MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view"));
86139566063dSJacob Faibussowitsch     PetscCall(MatSetOptionsPrefix(coarse_mat,((PetscObject)pcbddc->coarse_ksp)->prefix));
86149566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat));
86156e683305SStefano Zampini     if (pcbddc->dbg_flag) {
86169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level));
86176e683305SStefano Zampini     }
86186e683305SStefano Zampini   }
86199566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarseG));
86209566063dSJacob Faibussowitsch   PetscCall(PetscFree(isarray));
8621b1ecc7b1SStefano Zampini #if 0
8622b9b85e73SStefano Zampini   {
8623b9b85e73SStefano Zampini     PetscViewer viewer;
8624b9b85e73SStefano Zampini     char filename[256];
8625b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
86269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer));
86279566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB));
86289566063dSJacob Faibussowitsch     PetscCall(MatView(coarse_mat,viewer));
86299566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
86309566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
8631b9b85e73SStefano Zampini   }
8632b9b85e73SStefano Zampini #endif
8633f9eb5b7dSStefano Zampini 
86344f819b78SStefano Zampini   if (corners) {
86354f819b78SStefano Zampini     Vec            gv;
86364f819b78SStefano Zampini     IS             is;
86374f819b78SStefano Zampini     const PetscInt *idxs;
86384f819b78SStefano Zampini     PetscInt       i,d,N,n,cdim = pcbddc->mat_graph->cdim;
86394f819b78SStefano Zampini     PetscScalar    *coords;
86404f819b78SStefano Zampini 
864128b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->mat_graph->cloc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing local coordinates");
86429566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcbddc->coarse_vec,&N));
86439566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(pcbddc->coarse_vec,&n));
86449566063dSJacob Faibussowitsch     PetscCall(VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec),&gv));
86459566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(gv,cdim));
86469566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(gv,n*cdim,N*cdim));
86479566063dSJacob Faibussowitsch     PetscCall(VecSetType(gv,VECSTANDARD));
86489566063dSJacob Faibussowitsch     PetscCall(VecSetFromOptions(gv));
86499566063dSJacob Faibussowitsch     PetscCall(VecSet(gv,PETSC_MAX_REAL)); /* we only propagate coordinates from vertices constraints */
86504f819b78SStefano Zampini 
86519566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is));
86529566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is,&n));
86539566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,&idxs));
86549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n*cdim,&coords));
86554f819b78SStefano Zampini     for (i=0;i<n;i++) {
86564f819b78SStefano Zampini       for (d=0;d<cdim;d++) {
86574f819b78SStefano Zampini         coords[cdim*i+d] = pcbddc->mat_graph->coords[cdim*idxs[i]+d];
86584f819b78SStefano Zampini       }
86594f819b78SStefano Zampini     }
86609566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is,&idxs));
86619566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is));
86624f819b78SStefano Zampini 
86639566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(corners,&n));
86649566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(corners,&idxs));
86659566063dSJacob Faibussowitsch     PetscCall(VecSetValuesBlocked(gv,n,idxs,coords,INSERT_VALUES));
86669566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(corners,&idxs));
86679566063dSJacob Faibussowitsch     PetscCall(PetscFree(coords));
86689566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(gv));
86699566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(gv));
86709566063dSJacob Faibussowitsch     PetscCall(VecGetArray(gv,&coords));
86714f819b78SStefano Zampini     if (pcbddc->coarse_ksp) {
86724f819b78SStefano Zampini       PC        coarse_pc;
86734f819b78SStefano Zampini       PetscBool isbddc;
86744f819b78SStefano Zampini 
86759566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc));
86769566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc));
86774f819b78SStefano Zampini       if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */
86784f819b78SStefano Zampini         PetscReal *realcoords;
86794f819b78SStefano Zampini 
86809566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(gv,&n));
86814f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
86829566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(n,&realcoords));
86834f819b78SStefano Zampini         for (i=0;i<n;i++) realcoords[i] = PetscRealPart(coords[i]);
86844f819b78SStefano Zampini #else
86854f819b78SStefano Zampini         realcoords = coords;
86864f819b78SStefano Zampini #endif
86879566063dSJacob Faibussowitsch         PetscCall(PCSetCoordinates(coarse_pc,cdim,n/cdim,realcoords));
86884f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX)
86899566063dSJacob Faibussowitsch         PetscCall(PetscFree(realcoords));
86904f819b78SStefano Zampini #endif
86914f819b78SStefano Zampini       }
86924f819b78SStefano Zampini     }
86939566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(gv,&coords));
86949566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&gv));
86954f819b78SStefano Zampini   }
86969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&corners));
86974f819b78SStefano Zampini 
869898a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
869998a51de6SStefano Zampini     Vec crhs,csol;
870004708bb6SStefano Zampini 
87019566063dSJacob Faibussowitsch     PetscCall(KSPGetSolution(pcbddc->coarse_ksp,&csol));
87029566063dSJacob Faibussowitsch     PetscCall(KSPGetRhs(pcbddc->coarse_ksp,&crhs));
8703f347579bSStefano Zampini     if (!csol) {
87049566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL));
8705f9eb5b7dSStefano Zampini     }
8706f347579bSStefano Zampini     if (!crhs) {
87079566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs)));
8708f347579bSStefano Zampini     }
8709b0f5fe93SStefano Zampini   }
87109566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarsedivudotp));
8711b0f5fe93SStefano Zampini 
8712b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
8713b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
8714b0f5fe93SStefano Zampini 
87159566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->vec1_P,0.));
87164f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
87179566063dSJacob Faibussowitsch       PetscCall(VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES));
87184f1b2e48SStefano Zampini     }
87199566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcbddc->vec1_P));
87209566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcbddc->vec1_P));
87219566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD));
87229566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD));
8723b0f5fe93SStefano Zampini     if (coarse_mat) {
8724b0f5fe93SStefano Zampini       Vec         nullv;
8725b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
8726b0f5fe93SStefano Zampini       PetscInt    nl;
8727b0f5fe93SStefano Zampini 
87289566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(coarse_mat,&nullv,NULL));
87299566063dSJacob Faibussowitsch       PetscCall(VecGetLocalSize(nullv,&nl));
87309566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array));
87319566063dSJacob Faibussowitsch       PetscCall(VecGetArray(nullv,&array2));
87329566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(array2,array,nl));
87339566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(nullv,&array2));
87349566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array));
87359566063dSJacob Faibussowitsch       PetscCall(VecNormalize(nullv,NULL));
87369566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace));
87379566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&nullv));
8738b0f5fe93SStefano Zampini     }
8739b0f5fe93SStefano Zampini   }
87409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0));
8741b0f5fe93SStefano Zampini 
87429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0));
8743b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
8744b0f5fe93SStefano Zampini     PetscBool ispreonly;
8745b0f5fe93SStefano Zampini 
8746b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
8747b0f5fe93SStefano Zampini       PetscBool isnull;
87489566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull));
8749bef83e63SStefano Zampini       if (isnull) {
87509566063dSJacob Faibussowitsch         PetscCall(MatSetNullSpace(coarse_mat,CoarseNullSpace));
8751b0f5fe93SStefano Zampini       }
8752bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
8753b0f5fe93SStefano Zampini     }
8754b0f5fe93SStefano Zampini     /* setup coarse ksp */
87559566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcbddc->coarse_ksp));
8756cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
87579566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly));
87586e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) {
8759c8587f34SStefano Zampini       KSP       check_ksp;
87602b510759SStefano Zampini       KSPType   check_ksp_type;
8761c8587f34SStefano Zampini       PC        check_pc;
87626e683305SStefano Zampini       Vec       check_vec,coarse_vec;
87636a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
87642b510759SStefano Zampini       PetscInt  its;
87656e683305SStefano Zampini       PetscBool compute_eigs;
87666e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
87676e683305SStefano Zampini       PetscInt  neigs;
87688e185a42SStefano Zampini       const char *prefix;
8769c8587f34SStefano Zampini 
87702b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
87719566063dSJacob Faibussowitsch       PetscCall(KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp));
87729566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)check_ksp,(PetscObject)pcbddc->coarse_ksp,0));
87739566063dSJacob Faibussowitsch       PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,PETSC_FALSE));
87749566063dSJacob Faibussowitsch       PetscCall(KSPSetOperators(check_ksp,coarse_mat,coarse_mat));
87759566063dSJacob Faibussowitsch       PetscCall(KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size));
8776e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
87779566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(check_ksp,&check_pc));
87789566063dSJacob Faibussowitsch       PetscCall(PCSetType(check_pc,PCNONE));
87792b510759SStefano Zampini       if (ispreonly) {
87802b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
87816e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
87822b510759SStefano Zampini       } else {
8783cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
87846e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
8785c8587f34SStefano Zampini       }
87869566063dSJacob Faibussowitsch       PetscCall(KSPSetType(check_ksp,check_ksp_type));
87879566063dSJacob Faibussowitsch       PetscCall(KSPSetComputeSingularValues(check_ksp,compute_eigs));
87889566063dSJacob Faibussowitsch       PetscCall(KSPSetComputeEigenvalues(check_ksp,compute_eigs));
87899566063dSJacob Faibussowitsch       PetscCall(KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1));
87909566063dSJacob Faibussowitsch       PetscCall(KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix));
87919566063dSJacob Faibussowitsch       PetscCall(KSPSetOptionsPrefix(check_ksp,prefix));
87929566063dSJacob Faibussowitsch       PetscCall(KSPAppendOptionsPrefix(check_ksp,"check_"));
87939566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(check_ksp));
87949566063dSJacob Faibussowitsch       PetscCall(KSPSetUp(check_ksp));
87959566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(pcbddc->coarse_ksp,&check_pc));
87969566063dSJacob Faibussowitsch       PetscCall(KSPSetPC(check_ksp,check_pc));
8797c8587f34SStefano Zampini       /* create random vec */
87989566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(coarse_mat,&coarse_vec,&check_vec));
87999566063dSJacob Faibussowitsch       PetscCall(VecSetRandom(check_vec,NULL));
88009566063dSJacob Faibussowitsch       PetscCall(MatMult(coarse_mat,check_vec,coarse_vec));
8801c8587f34SStefano Zampini       /* solve coarse problem */
88029566063dSJacob Faibussowitsch       PetscCall(KSPSolve(check_ksp,coarse_vec,coarse_vec));
88039566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(check_ksp,pc,coarse_vec));
8804cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
88056e683305SStefano Zampini       if (compute_eigs) {
88069566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(pcbddc->coarse_size+1,&eigs_r));
88079566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(pcbddc->coarse_size+1,&eigs_c));
88089566063dSJacob Faibussowitsch         PetscCall(KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs));
88091ae86dd6SStefano Zampini         if (neigs) {
88106e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
88116e683305SStefano Zampini           lambda_min = eigs_r[0];
88126e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
88132701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
88149566063dSJacob Faibussowitsch               PetscCall(KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min));
88159566063dSJacob Faibussowitsch               PetscCall(KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min)));
8816cbcc2c2aSStefano Zampini             }
8817c8587f34SStefano Zampini           }
8818c8587f34SStefano Zampini         }
88191ae86dd6SStefano Zampini       }
8820cbcc2c2aSStefano Zampini 
8821c8587f34SStefano Zampini       /* check coarse problem residual error */
88226e683305SStefano Zampini       if (pcbddc->dbg_flag) {
88236e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
88249566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1)));
88259566063dSJacob Faibussowitsch         PetscCall(VecAXPY(check_vec,-1.0,coarse_vec));
88269566063dSJacob Faibussowitsch         PetscCall(VecNorm(check_vec,NORM_INFINITY,&infty_error));
88279566063dSJacob Faibussowitsch         PetscCall(MatMult(coarse_mat,check_vec,coarse_vec));
88289566063dSJacob Faibussowitsch         PetscCall(VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error));
88299566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates));
88309566063dSJacob Faibussowitsch         PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer));
88319566063dSJacob Faibussowitsch         PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer));
883263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",(double)infty_error));
883363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",(double)abs_infty_error));
8834b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
88359566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n"));
8836b0f5fe93SStefano Zampini         }
88376e683305SStefano Zampini         if (compute_eigs) {
88386e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
8839b03ebc13SStefano Zampini           KSPConvergedReason reason;
88409566063dSJacob Faibussowitsch           PetscCall(KSPGetType(check_ksp,&check_ksp_type));
88419566063dSJacob Faibussowitsch           PetscCall(KSPGetIterationNumber(check_ksp,&its));
88429566063dSJacob Faibussowitsch           PetscCall(KSPGetConvergedReason(check_ksp,&reason));
88439566063dSJacob Faibussowitsch           PetscCall(KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s));
884463a3b9bcSJacob 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));
88456e683305SStefano Zampini           for (i=0;i<neigs;i++) {
884663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",(double)eigs_r[i],(double)eigs_c[i]));
8847c8587f34SStefano Zampini           }
88486e683305SStefano Zampini         }
88499566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(dbg_viewer));
88509566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1)));
88516e683305SStefano Zampini       }
88529566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&check_vec));
88539566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&coarse_vec));
88549566063dSJacob Faibussowitsch       PetscCall(KSPDestroy(&check_ksp));
88556e683305SStefano Zampini       if (compute_eigs) {
88569566063dSJacob Faibussowitsch         PetscCall(PetscFree(eigs_r));
88579566063dSJacob Faibussowitsch         PetscCall(PetscFree(eigs_c));
8858c8587f34SStefano Zampini       }
88596e683305SStefano Zampini     }
88606e683305SStefano Zampini   }
88619566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&CoarseNullSpace));
8862cbcc2c2aSStefano Zampini   /* print additional info */
8863cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
88646e683305SStefano Zampini     /* waits until all processes reaches this point */
88659566063dSJacob Faibussowitsch     PetscCall(PetscBarrier((PetscObject)pc));
886663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %" PetscInt_FMT "\n",pcbddc->current_level));
88679566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
8868cbcc2c2aSStefano Zampini   }
8869cbcc2c2aSStefano Zampini 
88702b510759SStefano Zampini   /* free memory */
88719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&coarse_mat));
88729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0));
8873c8587f34SStefano Zampini   PetscFunctionReturn(0);
8874c8587f34SStefano Zampini }
8875674ae819SStefano Zampini 
8876f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
8877f34684f1SStefano Zampini {
8878f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8879f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
8880f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8881dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
8882dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
888373be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
8884dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
8885f34684f1SStefano Zampini 
8886f34684f1SStefano Zampini   PetscFunctionBegin;
8887f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
888808401ef6SPierre Jolivet   PetscCheck(!pcbddc->local_primal_size || pcbddc->local_primal_ref_node,PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
88899566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n));
88909566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset));
88919566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&subset_n));
88929566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult));
88939566063dSJacob Faibussowitsch   PetscCall(ISRenumber(subset,subset_mult,&coarse_size,&subset_n));
88949566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&subset));
88959566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&subset_mult));
88969566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(subset_n,&local_size));
889763a3b9bcSJacob 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);
88989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(local_size,&local_primal_indices));
88999566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(subset_n,&t_local_primal_indices));
89009566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(local_primal_indices,t_local_primal_indices,local_size));
89019566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(subset_n,&t_local_primal_indices));
89029566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&subset_n));
8903f34684f1SStefano Zampini 
8904f34684f1SStefano Zampini   /* check numbering */
8905f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
8906019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
8907dc456d91SStefano Zampini     PetscInt    i;
8908b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
8909f34684f1SStefano Zampini 
89109566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
89119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n"));
89129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n"));
89139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
8914019a44ceSStefano Zampini     /* counter */
89159566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_global,0.0));
89169566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_N,1.0));
89179566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
89189566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
89199566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
89209566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
89219566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_N,0.0));
8922f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
89239566063dSJacob Faibussowitsch       PetscCall(VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES));
8924f34684f1SStefano Zampini     }
89259566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec1_N));
89269566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec1_N));
89279566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_global,0.0));
89289566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
89299566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
89309566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
89319566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
89329566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcis->vec1_N,&array));
89339566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcis->vec2_N,&array2));
8934f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8935019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
89362c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
893775c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
8938b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
89399566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi));
894063a3b9bcSJacob 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));
8941f34684f1SStefano Zampini       }
8942f34684f1SStefano Zampini     }
89439566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcis->vec2_N,&array2));
89441c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
89459566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
8946f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
8947f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
8948f34684f1SStefano Zampini     }
89499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcis->vec1_N,&array));
89509566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_global,0.0));
89519566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
89529566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE));
89539566063dSJacob Faibussowitsch     PetscCall(VecSum(pcis->vec1_global,&coarsesum));
895463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %" PetscInt_FMT " (%lf)\n",coarse_size,(double)PetscRealPart(coarsesum)));
8955b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
8956ca8b9ea9SStefano Zampini       PetscInt *gidxs;
8957ca8b9ea9SStefano Zampini 
89589566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(pcbddc->local_primal_size,&gidxs));
89599566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs));
89609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n"));
89619566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
89629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank));
8963f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
896463a3b9bcSJacob 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]));
8965f34684f1SStefano Zampini       }
89669566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
89679566063dSJacob Faibussowitsch       PetscCall(PetscFree(gidxs));
8968f34684f1SStefano Zampini     }
89699566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
89709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
897128b400f6SJacob Faibussowitsch     PetscCheck(!set_error_reduced,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
8972f34684f1SStefano Zampini   }
89736080607fSStefano Zampini 
8974f34684f1SStefano Zampini   /* get back data */
8975f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
8976f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
8977674ae819SStefano Zampini   PetscFunctionReturn(0);
8978674ae819SStefano Zampini }
8979674ae819SStefano Zampini 
8980a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
8981e456f2a8SStefano Zampini {
8982e456f2a8SStefano Zampini   IS             localis_t;
8983a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
8984e456f2a8SStefano Zampini   PetscScalar    *vals;
8985e456f2a8SStefano Zampini 
8986e456f2a8SStefano Zampini   PetscFunctionBegin;
8987a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
89889566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(globalis,&lsize));
89899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(lsize,&vals));
8990e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
89919566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(globalis,(const PetscInt**)&idxs));
89929566063dSJacob Faibussowitsch   PetscCall(VecSet(gwork,0.0));
89939566063dSJacob Faibussowitsch   PetscCall(VecSet(lwork,0.0));
89941035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
89959566063dSJacob Faibussowitsch     PetscCall(VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE));
89969566063dSJacob Faibussowitsch     PetscCall(VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES));
89971035eff8SStefano Zampini   }
89989566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(gwork));
89999566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(globalis,(const PetscInt**)&idxs));
90009566063dSJacob Faibussowitsch   PetscCall(PetscFree(vals));
90019566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(gwork));
9002a7dc3881SStefano Zampini   /* now compute set in local ordering */
90039566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD));
90049566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD));
90059566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(lwork,(const PetscScalar**)&vals));
90069566063dSJacob Faibussowitsch   PetscCall(VecGetSize(lwork,&n));
9007a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
9008ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
9009e456f2a8SStefano Zampini       lsize++;
9010e456f2a8SStefano Zampini     }
9011e456f2a8SStefano Zampini   }
90129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(lsize,&idxs));
9013a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
9014ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
9015e456f2a8SStefano Zampini       idxs[lsize++] = i;
9016e456f2a8SStefano Zampini     }
9017e456f2a8SStefano Zampini   }
90189566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(lwork,(const PetscScalar**)&vals));
90199566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t));
9020e456f2a8SStefano Zampini   *localis = localis_t;
9021e456f2a8SStefano Zampini   PetscFunctionReturn(0);
9022e456f2a8SStefano Zampini }
9023906d46d4SStefano Zampini 
902408122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
9025b96c3477SStefano Zampini {
9026a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9027b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9028b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
9029a64f4aa4SStefano Zampini   Mat                 S_j;
9030b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
9031b96c3477SStefano Zampini   PetscBool           free_used_adj;
9032b96c3477SStefano Zampini 
9033b96c3477SStefano Zampini   PetscFunctionBegin;
90349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0));
9035b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
9036b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
903708122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
9038b96c3477SStefano Zampini     used_xadj = NULL;
9039b96c3477SStefano Zampini     used_adjncy = NULL;
9040b96c3477SStefano Zampini   } else {
904108122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
904208122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
904308122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
904408122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
9045b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
9046b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
9047b96c3477SStefano Zampini     } else {
90482fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
9049b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
9050b96c3477SStefano Zampini       PetscInt       nvtxs;
9051b96c3477SStefano Zampini 
90529566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row));
90532fffb893SStefano Zampini       if (flg_row) {
90549566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy));
90559566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(used_xadj,xadj,nvtxs+1));
90569566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(used_adjncy,adjncy,xadj[nvtxs]));
9057b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
90582fffb893SStefano Zampini       } else {
90592fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
90602fffb893SStefano Zampini         used_xadj = NULL;
90612fffb893SStefano Zampini         used_adjncy = NULL;
90622fffb893SStefano Zampini       }
90639566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row));
9064b96c3477SStefano Zampini     }
9065b96c3477SStefano Zampini   }
9066d5574798SStefano Zampini 
9067d5574798SStefano Zampini   /* setup sub_schurs data */
90689566063dSJacob Faibussowitsch   PetscCall(MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j));
9069df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
9070df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
90719566063dSJacob Faibussowitsch     PetscCall(MatSchurComplementSetKSP(S_j,pcbddc->ksp_D));
90729566063dSJacob 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));
9073a64f4aa4SStefano Zampini   } else {
907472b8c272SStefano Zampini     Mat       change = NULL;
90759d54b7f4SStefano Zampini     Vec       scaling = NULL;
9076111315fdSstefano_zampini     IS        change_primal = NULL, iP;
9077111315fdSstefano_zampini     PetscInt  benign_n;
9078111315fdSstefano_zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
90797ebab0bbSStefano Zampini     PetscBool need_change = PETSC_FALSE;
9080111315fdSstefano_zampini     PetscBool discrete_harmonic = PETSC_FALSE;
9081a3df083aSStefano Zampini 
90825feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
90835feab87aSStefano Zampini       PetscInt n_vertices;
90845feab87aSStefano Zampini 
90859566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(sub_schurs->is_vertices,&n_vertices));
90862034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
90875feab87aSStefano Zampini     }
9088a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
9089a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
9090ca92afb2SStefano Zampini     } else {
9091a3df083aSStefano Zampini       benign_n = 0;
9092ca92afb2SStefano Zampini     }
9093b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
9094b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
9095b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
909672b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
909722db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
90981c2dc1cbSBarry Smith       PetscCall(MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
909922db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
9100b7ab4a40SStefano Zampini     }
9101b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
9102b7ab4a40SStefano Zampini        We need to compute the change of basis according to the quadrature weights attached to pmat via MatSetNearNullSpace, and this could not be done (at the moment) without some hacking */
9103b7ab4a40SStefano Zampini     if (need_change) {
910488c03ad3SStefano Zampini       PC_IS   *pcisf;
910588c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
910688c03ad3SStefano Zampini       PC      pcf;
910788c03ad3SStefano Zampini 
910828b400f6SJacob Faibussowitsch       PetscCheck(!pcbddc->sub_schurs_rebuild,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
91099566063dSJacob Faibussowitsch       PetscCall(PCCreate(PetscObjectComm((PetscObject)pc),&pcf));
91109566063dSJacob Faibussowitsch       PetscCall(PCSetOperators(pcf,pc->mat,pc->pmat));
91119566063dSJacob Faibussowitsch       PetscCall(PCSetType(pcf,PCBDDC));
9112b9be95fcSstefano_zampini 
911388c03ad3SStefano Zampini       /* hacks */
911488c03ad3SStefano Zampini       pcisf                        = (PC_IS*)pcf->data;
911572b8c272SStefano Zampini       pcisf->is_B_local            = pcis->is_B_local;
911672b8c272SStefano Zampini       pcisf->vec1_N                = pcis->vec1_N;
911772b8c272SStefano Zampini       pcisf->BtoNmap               = pcis->BtoNmap;
911872b8c272SStefano Zampini       pcisf->n                     = pcis->n;
911972b8c272SStefano Zampini       pcisf->n_B                   = pcis->n_B;
912088c03ad3SStefano Zampini       pcbddcf                      = (PC_BDDC*)pcf->data;
91219566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddcf->mat_graph));
912288c03ad3SStefano Zampini       pcbddcf->mat_graph           = pcbddc->mat_graph;
912388c03ad3SStefano Zampini       pcbddcf->use_faces           = PETSC_TRUE;
912488c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
912588c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
912672b8c272SStefano Zampini       pcbddcf->use_qr_single       = PETSC_TRUE;
912788c03ad3SStefano Zampini       pcbddcf->fake_change         = PETSC_TRUE;
9128b9be95fcSstefano_zampini 
9129b9be95fcSstefano_zampini       /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */
91309566063dSJacob Faibussowitsch       PetscCall(PCBDDCConstraintsSetUp(pcf));
913172b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
91329566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal));
913372b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
913472b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
9135b9be95fcSstefano_zampini 
913688c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
91379566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddcf->sub_schurs));
91389566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&pcbddcf->onearnullspace));
91399566063dSJacob Faibussowitsch       PetscCall(PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult));
91409566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddcf->primal_indices_local_idxs));
91419566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcbddcf->onearnullvecs_state));
91429566063dSJacob Faibussowitsch       PetscCall(PetscFree(pcf->data));
914388c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
9144b9be95fcSstefano_zampini       pcf->ops->reset   = NULL;
91459566063dSJacob Faibussowitsch       PetscCall(PCDestroy(&pcf));
914688c03ad3SStefano Zampini     }
91479d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
9148111315fdSstefano_zampini 
91499566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP));
9150111315fdSstefano_zampini     if (iP) {
9151d0609cedSBarry Smith       PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");
91529566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL));
9153d0609cedSBarry Smith       PetscOptionsEnd();
9154111315fdSstefano_zampini     }
9155111315fdSstefano_zampini     if (discrete_harmonic) {
9156111315fdSstefano_zampini       Mat A;
91579566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A));
91589566063dSJacob Faibussowitsch       PetscCall(MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL));
91599566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP));
91609566063dSJacob 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));
91619566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A));
9162111315fdSstefano_zampini     } else {
91639566063dSJacob 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));
9164111315fdSstefano_zampini     }
91659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&change));
91669566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&change_primal));
9167ca92afb2SStefano Zampini   }
91689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S_j));
9169b96c3477SStefano Zampini 
9170b96c3477SStefano Zampini   /* free adjacency */
9171b96c3477SStefano Zampini   if (free_used_adj) {
91729566063dSJacob Faibussowitsch     PetscCall(PetscFree2(used_xadj,used_adjncy));
9173b96c3477SStefano Zampini   }
91749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0));
9175b96c3477SStefano Zampini   PetscFunctionReturn(0);
9176b96c3477SStefano Zampini }
9177b96c3477SStefano Zampini 
917808122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
9179b96c3477SStefano Zampini {
9180b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9181b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9182b96c3477SStefano Zampini   PCBDDCGraph         graph;
9183b96c3477SStefano Zampini 
9184b96c3477SStefano Zampini   PetscFunctionBegin;
9185b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
918608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
91873301b35fSStefano Zampini     IS       verticesIS,verticescomm;
91883301b35fSStefano Zampini     PetscInt vsize,*idxs;
9189b96c3477SStefano Zampini 
91909566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS));
91919566063dSJacob Faibussowitsch     PetscCall(ISGetSize(verticesIS,&vsize));
91929566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(verticesIS,(const PetscInt**)&idxs));
91939566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm));
91949566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(verticesIS,(const PetscInt**)&idxs));
91959566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS));
91969566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphCreate(&graph));
91979566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount));
91989566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm));
91999566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&verticescomm));
92009566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphComputeConnectedComponents(graph));
9201b96c3477SStefano Zampini   } else {
9202b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
9203b96c3477SStefano Zampini   }
9204e4d548c7SStefano Zampini   /* print some info */
92055c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
9206e4d548c7SStefano Zampini     IS       vertices;
9207e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
92089566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer));
92099566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices));
92109566063dSJacob Faibussowitsch     PetscCall(ISGetSize(vertices,&nv));
92119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
92129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n"));
921363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices));
921463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges));
921563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02" PetscInt_FMT " local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces));
92169566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
92179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
92189566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices));
9219e4d548c7SStefano Zampini   }
9220b96c3477SStefano Zampini 
9221b96c3477SStefano Zampini   /* sub_schurs init */
9222b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
92239566063dSJacob Faibussowitsch     PetscCall(PCBDDCSubSchursCreate(&pcbddc->sub_schurs));
9224b334f244SStefano Zampini   }
92259566063dSJacob Faibussowitsch   PetscCall(PCBDDCSubSchursInit(pcbddc->sub_schurs,((PetscObject)pc)->prefix,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_rebuild));
9226a64f4aa4SStefano Zampini 
9227b96c3477SStefano Zampini   /* free graph struct */
922808122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
92299566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphDestroy(&graph));
9230b96c3477SStefano Zampini   }
9231b96c3477SStefano Zampini   PetscFunctionReturn(0);
9232b96c3477SStefano Zampini }
9233fa34dd3eSStefano Zampini 
9234fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
9235fa34dd3eSStefano Zampini {
9236fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
9237fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
9238fa34dd3eSStefano Zampini 
9239fa34dd3eSStefano Zampini   PetscFunctionBegin;
9240fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
9241fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
92424f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
9243fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
92444f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
924575c01103SStefano Zampini     PetscReal      norm;
9246fa34dd3eSStefano Zampini     PetscInt       i;
9247fa34dd3eSStefano Zampini 
9248fa34dd3eSStefano Zampini     /* B0 and B0_B */
9249fa34dd3eSStefano Zampini     if (zerodiag) {
9250fa34dd3eSStefano Zampini       IS       dummy;
9251fa34dd3eSStefano Zampini 
92529566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy));
92539566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B));
92549566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(B0_B,NULL,&dummy_vec));
92559566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dummy));
9256fa34dd3eSStefano Zampini     }
9257fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
92589566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcbddc->vec1_P,&vec_scale_P));
92599566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->vec1_P,1.0));
92609566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD));
92619566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD));
92629566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE));
92639566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE));
92649566063dSJacob Faibussowitsch     PetscCall(VecReciprocal(vec_scale_P));
9265fa34dd3eSStefano Zampini     /* S_j */
92669566063dSJacob Faibussowitsch     PetscCall(MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j));
92679566063dSJacob Faibussowitsch     PetscCall(MatSchurComplementSetKSP(S_j,pcbddc->ksp_D));
9268fa34dd3eSStefano Zampini 
9269fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
92709566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(pcis->vec1_N,NULL));
9271fa34dd3eSStefano Zampini     /* continuous in primal space */
92729566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(pcbddc->coarse_vec,NULL));
92739566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE));
92749566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE));
92759566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcbddc->vec1_P,&array));
92769566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(pcbddc->benign_n,&p0_check));
92774f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
92789566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES));
92799566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcbddc->vec1_P,&array));
92809566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec1_N));
92819566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec1_N));
92829566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD));
92839566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD));
92849566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec2_B,&vec_check_B));
92859566063dSJacob Faibussowitsch     PetscCall(VecCopy(pcis->vec2_B,vec_check_B));
9286fa34dd3eSStefano Zampini 
9287fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
9288fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
9289fa34dd3eSStefano Zampini     /* local with Schur */
92909566063dSJacob Faibussowitsch     PetscCall(MatMult(S_j,pcis->vec2_B,pcis->vec1_B));
9291fa34dd3eSStefano Zampini     if (zerodiag) {
92929566063dSJacob Faibussowitsch       PetscCall(VecGetArray(dummy_vec,&array));
92934f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
92949566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(dummy_vec,&array));
92959566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B));
9296fa34dd3eSStefano Zampini     }
9297fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
92989566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
92999566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
93009566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcis->vec1_N,&array));
93019566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcbddc->vec1_P,&array2));
9302fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
93039566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcbddc->vec1_P,&array2));
93049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcis->vec1_N,&array));
93059566063dSJacob Faibussowitsch     PetscCall(VecSet(pcbddc->coarse_vec,0.));
93069566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD));
93079566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD));
93089566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE));
93099566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE));
93109566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcbddc->vec1_P,&array));
9311fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
93129566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P));
93139566063dSJacob Faibussowitsch     PetscCall(VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES));
93149566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcbddc->vec1_P,&array));
93159566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(pcis->vec1_N));
93169566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(pcis->vec1_N));
93179566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
93189566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
9319fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
9320fa34dd3eSStefano Zampini     if (zerodiag) {
93219566063dSJacob Faibussowitsch       PetscCall(MatMult(B0_B,pcis->vec2_B,dummy_vec));
93229566063dSJacob Faibussowitsch       PetscCall(VecGetArray(dummy_vec,&array));
93234f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
93249566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(dummy_vec,&array));
9325fa34dd3eSStefano Zampini     }
9326fa34dd3eSStefano Zampini     /* BDDC */
93279566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_D,0.));
93289566063dSJacob Faibussowitsch     PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE));
9329fa34dd3eSStefano Zampini 
93309566063dSJacob Faibussowitsch     PetscCall(VecCopy(pcis->vec1_B,pcis->vec2_B));
93319566063dSJacob Faibussowitsch     PetscCall(VecAXPY(pcis->vec1_B,-1.0,vec_check_B));
93329566063dSJacob Faibussowitsch     PetscCall(VecNorm(pcis->vec1_B,NORM_INFINITY,&norm));
933363a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,(double)norm));
93344f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
933563a3b9bcSJacob 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])));
9336fa34dd3eSStefano Zampini     }
93379566063dSJacob Faibussowitsch     PetscCall(PetscFree(p0_check));
93389566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vec_scale_P));
93399566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&vec_check_B));
93409566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&dummy_vec));
93419566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&S_j));
93429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B0_B));
9343fa34dd3eSStefano Zampini   }
9344fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
9345fa34dd3eSStefano Zampini }
93461e0482f5SStefano Zampini 
93471e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
93481e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
93491e0482f5SStefano Zampini {
93501e0482f5SStefano Zampini   Mat            At;
93511e0482f5SStefano Zampini   IS             rows;
93521e0482f5SStefano Zampini   PetscInt       rst,ren;
93531e0482f5SStefano Zampini   PetscLayout    rmap;
93541e0482f5SStefano Zampini 
93551e0482f5SStefano Zampini   PetscFunctionBegin;
93561e0482f5SStefano Zampini   rst = ren = 0;
93571e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
93589566063dSJacob Faibussowitsch     PetscCall(PetscLayoutCreate(ccomm,&rmap));
93599566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetSize(rmap,A->rmap->N));
93609566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetBlockSize(rmap,1));
93619566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp(rmap));
93629566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetRange(rmap,&rst,&ren));
93631e0482f5SStefano Zampini   }
93649566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows));
93659566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At));
93669566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&rows));
93671e0482f5SStefano Zampini 
93681e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
93691e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
93701e0482f5SStefano Zampini     IS         from,to;
93711e0482f5SStefano Zampini     Vec        gvec;
93721e0482f5SStefano Zampini     PetscInt   lsize;
93731e0482f5SStefano Zampini 
93749566063dSJacob Faibussowitsch     PetscCall(MatCreate(ccomm,B));
93759566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N));
93769566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B,MATAIJ));
93779566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&((*B)->rmap)));
93789566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp((*B)->cmap));
93791e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
93801e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
93819566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(ccomm,&b->size));
93829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(ccomm,&b->rank));
93839566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)a->A));
93849566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)a->B));
93851e0482f5SStefano Zampini     b->A = a->A;
93861e0482f5SStefano Zampini     b->B = a->B;
93871e0482f5SStefano Zampini 
93881e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
93891e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
93900a545947SLisandro Dalcin     b->rowindices      = NULL;
93910a545947SLisandro Dalcin     b->rowvalues       = NULL;
93921e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
93931e0482f5SStefano Zampini 
93941e0482f5SStefano Zampini     (*B)->rmap         = rmap;
93951e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
93961e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
93971e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
93981e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
93991e0482f5SStefano Zampini 
94001e0482f5SStefano Zampini     if (a->colmap) {
94011e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
94029566063dSJacob Faibussowitsch       PetscCall(PetscTableCreateCopy(a->colmap,&b->colmap));
94031e0482f5SStefano Zampini #else
94049566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(At->cmap->N,&b->colmap));
94059566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt)));
94069566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(b->colmap,a->colmap,At->cmap->N));
94071e0482f5SStefano Zampini #endif
94080a545947SLisandro Dalcin     } else b->colmap = NULL;
94091e0482f5SStefano Zampini     if (a->garray) {
94101e0482f5SStefano Zampini       PetscInt len;
94111e0482f5SStefano Zampini       len  = a->B->cmap->n;
94129566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(len+1,&b->garray));
94139566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt)));
94149566063dSJacob Faibussowitsch       if (len) PetscCall(PetscArraycpy(b->garray,a->garray,len));
94150a545947SLisandro Dalcin     } else b->garray = NULL;
94161e0482f5SStefano Zampini 
94179566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)a->lvec));
94181e0482f5SStefano Zampini     b->lvec = a->lvec;
94199566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec));
94201e0482f5SStefano Zampini 
94211e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
94229566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(b->lvec,&lsize));
94239566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from));
94249566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to));
94259566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(*B,&gvec,NULL));
94269566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx));
94279566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx));
94289566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&from));
94299566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&to));
94309566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&gvec));
94311e0482f5SStefano Zampini   }
94329566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&At));
94331e0482f5SStefano Zampini   PetscFunctionReturn(0);
94341e0482f5SStefano Zampini }
9435