xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 339f8db1bf3223986247a592b0580ac91037d0a1)
1ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
3674ae819SStefano Zampini #include <petscblaslapack.h>
4674ae819SStefano Zampini 
5906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y);
6906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y);
7906d46d4SStefano Zampini 
8674ae819SStefano Zampini #undef __FUNCT__
9*339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
10*339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
11*339f8db1SStefano Zampini {
12*339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
13*339f8db1SStefano Zampini   IS             zerodiag;
14*339f8db1SStefano Zampini   PetscInt       nz;
15*339f8db1SStefano Zampini   PetscBool      sorted;
16*339f8db1SStefano Zampini   PetscErrorCode ierr;
17*339f8db1SStefano Zampini 
18*339f8db1SStefano Zampini   PetscFunctionBegin;
19*339f8db1SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
20*339f8db1SStefano Zampini   ierr = PetscObjectReference((PetscObject)pcbddc->local_mat);CHKERRQ(ierr);
21*339f8db1SStefano Zampini   pcbddc->benign_original_mat = pcbddc->local_mat;
22*339f8db1SStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->benign_original_mat,&zerodiag);CHKERRQ(ierr);
23*339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
24*339f8db1SStefano Zampini   if (!sorted) {
25*339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
26*339f8db1SStefano Zampini   }
27*339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
28*339f8db1SStefano Zampini   if (nz) {
29*339f8db1SStefano Zampini     IS                zerodiagc;
30*339f8db1SStefano Zampini     PetscScalar       *array;
31*339f8db1SStefano Zampini     const PetscInt    *idxs,*idxsc;
32*339f8db1SStefano Zampini     PetscInt          i,n,*nnz;
33*339f8db1SStefano Zampini 
34*339f8db1SStefano Zampini     /* TODO: add check for shared dofs and raise error */
35*339f8db1SStefano Zampini     ierr = MatGetLocalSize(pcbddc->benign_original_mat,&n,NULL);CHKERRQ(ierr);
36*339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
37*339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
38*339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
39*339f8db1SStefano Zampini     /* local change of basis for pressures */
40*339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
41*339f8db1SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->benign_original_mat),&pcbddc->benign_change);CHKERRQ(ierr);
42*339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
43*339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
44*339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
45*339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities */
46*339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) nnz[idxs[i]] = 2; /* change on pressures */
47*339f8db1SStefano Zampini     nnz[idxs[nz-1]] = nz; /* last local pressure dof: _0 set */
48*339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
49*339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
50*339f8db1SStefano Zampini     /* set identity on velocities */
51*339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
52*339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
53*339f8db1SStefano Zampini     }
54*339f8db1SStefano Zampini     /* set change on pressures */
55*339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) {
56*339f8db1SStefano Zampini       PetscScalar vals[2];
57*339f8db1SStefano Zampini       PetscInt    cols[2];
58*339f8db1SStefano Zampini 
59*339f8db1SStefano Zampini       /* TODO: add quadrature */
60*339f8db1SStefano Zampini       cols[0] = idxs[i];
61*339f8db1SStefano Zampini       cols[1] = idxs[nz-1];
62*339f8db1SStefano Zampini       vals[0] = 1.;
63*339f8db1SStefano Zampini       vals[1] = 1./nz;
64*339f8db1SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+i,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
65*339f8db1SStefano Zampini     }
66*339f8db1SStefano Zampini     ierr = PetscMalloc1(nz,&array);CHKERRQ(ierr);
67*339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) array[i] = -1.;
68*339f8db1SStefano Zampini     array[nz-1] = 1./nz;
69*339f8db1SStefano Zampini     ierr = MatSetValues(pcbddc->benign_change,1,idxs+nz-1,nz,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
70*339f8db1SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
71*339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
72*339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
73*339f8db1SStefano Zampini     /* TODO: need optimization? */
74*339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
75*339f8db1SStefano Zampini     ierr = MatPtAP(pcbddc->benign_original_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
76*339f8db1SStefano Zampini     /* store local and global idxs for p0 */
77*339f8db1SStefano Zampini     pcbddc->benign_p0_lidx = idxs[nz-1];
78*339f8db1SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,1,&idxs[nz-1],&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
79*339f8db1SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
80*339f8db1SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
81*339f8db1SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
82*339f8db1SStefano Zampini   } else { /* this is unlikely to happen but, just in case, destroy the empty IS */
83*339f8db1SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
84*339f8db1SStefano Zampini   }
85*339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
86*339f8db1SStefano Zampini   PetscFunctionReturn(0);
87*339f8db1SStefano Zampini }
88*339f8db1SStefano Zampini 
89*339f8db1SStefano Zampini #undef __FUNCT__
90015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
91015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
92efc2fbd9SStefano Zampini {
93efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
94efc2fbd9SStefano Zampini   PetscErrorCode ierr;
95efc2fbd9SStefano Zampini 
96efc2fbd9SStefano Zampini   PetscFunctionBegin;
97efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
98efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
99c9ed8603SStefano Zampini     if (pcbddc->benign_p0_gidx >= 0) {
100efc2fbd9SStefano Zampini       ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,1,NULL,PETSC_OWN_POINTER,&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
101c9ed8603SStefano Zampini     } else {
102c9ed8603SStefano Zampini       ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,0,NULL,PETSC_OWN_POINTER,&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
103c9ed8603SStefano Zampini     }
104efc2fbd9SStefano Zampini   }
105015636ebSStefano Zampini   if (get) { /* use SF to get values */
106efc2fbd9SStefano Zampini     PetscScalar *array;
107efc2fbd9SStefano Zampini 
108efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
109efc2fbd9SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,&pcbddc->benign_p0);CHKERRQ(ierr);
110efc2fbd9SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,&pcbddc->benign_p0);CHKERRQ(ierr);
111efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
112efc2fbd9SStefano Zampini   } else { /* use VecSetValue */
113c9ed8603SStefano Zampini     if (pcbddc->benign_p0_gidx >= 0) {
114efc2fbd9SStefano Zampini       ierr = VecSetValue(v,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
115c9ed8603SStefano Zampini     }
116efc2fbd9SStefano Zampini     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
117efc2fbd9SStefano Zampini     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
118efc2fbd9SStefano Zampini   }
119efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
120efc2fbd9SStefano Zampini }
121efc2fbd9SStefano Zampini 
122efc2fbd9SStefano Zampini #undef __FUNCT__
123c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
124c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
125c263805aSStefano Zampini {
126c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
127c263805aSStefano Zampini   PetscErrorCode ierr;
128c263805aSStefano Zampini 
129c263805aSStefano Zampini   PetscFunctionBegin;
130c263805aSStefano Zampini   /* TODO: add error checking
131c263805aSStefano Zampini     - avoid nested pop (or push) calls.
132c263805aSStefano Zampini     - cannot push before pop.
1331c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
134c263805aSStefano Zampini   */
135c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx < 0) {
136efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
137efc2fbd9SStefano Zampini   }
138c263805aSStefano Zampini   if (pop) {
139c263805aSStefano Zampini     const PetscInt    *cB0_cols;
140c263805aSStefano Zampini     PetscInt          cB0_ncol;
141c263805aSStefano Zampini     const PetscScalar *cB0_vals;
142c263805aSStefano Zampini 
143c263805aSStefano Zampini     /* extract B_0 */
144efc2fbd9SStefano Zampini     ierr = MatGetRow(pcbddc->local_mat,pcbddc->benign_p0_lidx,&cB0_ncol,&cB0_cols,&cB0_vals);CHKERRQ(ierr);
145c263805aSStefano Zampini     pcbddc->B0_ncol = cB0_ncol;
146c263805aSStefano Zampini     ierr = PetscFree2(pcbddc->B0_cols,pcbddc->B0_vals);CHKERRQ(ierr);
147c263805aSStefano Zampini     ierr = PetscMalloc2(cB0_ncol,&pcbddc->B0_cols,cB0_ncol,&pcbddc->B0_vals);CHKERRQ(ierr);
148c263805aSStefano Zampini     ierr = PetscMemcpy(pcbddc->B0_cols,cB0_cols,cB0_ncol*sizeof(PetscInt));CHKERRQ(ierr);
149c263805aSStefano Zampini     ierr = PetscMemcpy(pcbddc->B0_vals,cB0_vals,cB0_ncol*sizeof(PetscScalar));CHKERRQ(ierr);
150efc2fbd9SStefano Zampini     ierr = MatRestoreRow(pcbddc->local_mat,pcbddc->benign_p0_lidx,&cB0_ncol,&cB0_cols,&cB0_vals);CHKERRQ(ierr);
151c263805aSStefano Zampini     /* remove rows and cols from local problem */
152c263805aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
153efc2fbd9SStefano Zampini     ierr = MatZeroRowsColumns(pcbddc->local_mat,1,&pcbddc->benign_p0_lidx,1.,NULL,NULL);CHKERRQ(ierr);
154c263805aSStefano Zampini   } else { /* push */
155efc2fbd9SStefano Zampini     ierr = MatSetValues(pcbddc->local_mat,1,&pcbddc->benign_p0_lidx,pcbddc->B0_ncol,pcbddc->B0_cols,pcbddc->B0_vals,INSERT_VALUES);CHKERRQ(ierr);
156efc2fbd9SStefano Zampini     ierr = MatSetValues(pcbddc->local_mat,pcbddc->B0_ncol,pcbddc->B0_cols,1,&pcbddc->benign_p0_lidx,pcbddc->B0_vals,INSERT_VALUES);CHKERRQ(ierr);
157efc2fbd9SStefano Zampini     ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx,pcbddc->benign_p0_lidx,0.0,INSERT_VALUES);CHKERRQ(ierr);
158c263805aSStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
159c263805aSStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
160c263805aSStefano Zampini   }
161c263805aSStefano Zampini   PetscFunctionReturn(0);
162c263805aSStefano Zampini }
163c263805aSStefano Zampini 
164c263805aSStefano Zampini #undef __FUNCT__
165b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
16608122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
167b1b3d7a2SStefano Zampini {
168b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
16908122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
17008122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
17108122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
17208122e43SStefano Zampini   PetscScalar     *work,lwork;
17308122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
17408122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
17508122e43SStefano Zampini   PetscReal       *eigs,thresh;
1761b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
177f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
17808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
17908122e43SStefano Zampini   PetscReal       *rwork;
18008122e43SStefano Zampini #endif
181b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
182b1b3d7a2SStefano Zampini 
183b1b3d7a2SStefano Zampini   PetscFunctionBegin;
18408122e43SStefano Zampini   if (!sub_schurs->use_mumps) {
18508122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
18608122e43SStefano Zampini   }
18708122e43SStefano Zampini 
18806a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
18906a4e24aSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adaptive selection not yet implemented for general matrix pencils (herm %d, posdef %d)\n",sub_schurs->is_hermitian,sub_schurs->is_posdef);
19006a4e24aSStefano Zampini   }
19106a4e24aSStefano Zampini 
192fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
193fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
194fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
195fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
196fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
197fd14bc51SStefano Zampini   }
198fd14bc51SStefano Zampini 
199e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
200e496cd5dSStefano Zampini     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %d (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef);
201e496cd5dSStefano Zampini   }
202e496cd5dSStefano Zampini 
20308122e43SStefano Zampini   /* max size of subsets */
20408122e43SStefano Zampini   mss = 0;
20508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
20608122e43SStefano Zampini     PetscInt subset_size;
207862806e4SStefano Zampini 
20808122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
20908122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
21008122e43SStefano Zampini   }
21108122e43SStefano Zampini 
21208122e43SStefano Zampini   /* min/max and threshold */
21308122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
214f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
21508122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
216f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
217f6f667cfSStefano Zampini   if (nmin) {
218f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
219f6f667cfSStefano Zampini   }
22008122e43SStefano Zampini 
22108122e43SStefano Zampini   /* allocate lapack workspace */
22208122e43SStefano Zampini   cum = cum2 = 0;
22308122e43SStefano Zampini   maxneigs = 0;
22408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
22508122e43SStefano Zampini     PetscInt n,subset_size;
226f6f667cfSStefano Zampini 
22708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
22808122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
2299162d606SStefano Zampini     cum += subset_size;
2309162d606SStefano Zampini     cum2 += subset_size*n;
23108122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
23208122e43SStefano Zampini   }
23308122e43SStefano Zampini   if (mss) {
2349ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
23508122e43SStefano Zampini       PetscBLASInt B_itype = 1;
23608122e43SStefano Zampini       PetscBLASInt B_N = mss;
2374c6709b3SStefano Zampini       PetscReal    zero = 0.0;
2384c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
23908122e43SStefano Zampini 
24008122e43SStefano Zampini       B_lwork = -1;
24108122e43SStefano Zampini       S = NULL;
24208122e43SStefano Zampini       St = NULL;
243a58a30b4SStefano Zampini       eigs = NULL;
244a58a30b4SStefano Zampini       eigv = NULL;
245a58a30b4SStefano Zampini       B_iwork = NULL;
246a58a30b4SStefano Zampini       B_ifail = NULL;
247d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
248d1710679SStefano Zampini       rwork = NULL;
249d1710679SStefano Zampini #endif
2508bec7fa6SStefano Zampini       thresh = 1.0;
25108122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
25208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25308122e43SStefano 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));
25408122e43SStefano Zampini #else
25508122e43SStefano 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));
25608122e43SStefano Zampini #endif
25708122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
25808122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
25908122e43SStefano Zampini     } else {
26008122e43SStefano Zampini         /* TODO */
26108122e43SStefano Zampini     }
26208122e43SStefano Zampini   } else {
26308122e43SStefano Zampini     lwork = 0;
26408122e43SStefano Zampini   }
26508122e43SStefano Zampini 
26608122e43SStefano Zampini   nv = 0;
267d62866d3SStefano 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) */
268d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
26908122e43SStefano Zampini   }
2704c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
271f6f667cfSStefano Zampini   if (allocated_S_St) {
272f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
273f6f667cfSStefano Zampini   }
274f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
27508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
27608122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
27708122e43SStefano Zampini #endif
2789162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
2799162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
2809162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
28108122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
2829162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
28308122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
28408122e43SStefano Zampini 
28508122e43SStefano Zampini   maxneigs = 0;
28608122e43SStefano Zampini   cum = cum2 = cumarray = 0;
2879162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
2889162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
289d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
29008122e43SStefano Zampini     const PetscInt *idxs;
29108122e43SStefano Zampini 
292d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
29308122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
29408122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
29508122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
29608122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
2979162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
2989162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
29908122e43SStefano Zampini     }
30008122e43SStefano Zampini     cum2 = cum;
301d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
30208122e43SStefano Zampini   }
30308122e43SStefano Zampini 
30408122e43SStefano Zampini   if (mss) { /* multilevel */
30508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
30608122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
30708122e43SStefano Zampini   }
30808122e43SStefano Zampini 
30908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
31008122e43SStefano Zampini 
31108122e43SStefano Zampini     const PetscInt *idxs;
312f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
313862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
31408122e43SStefano Zampini     PetscBLASInt   B_N;
315aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
31608122e43SStefano Zampini 
317862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
318f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
319f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3209ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
321aff50787SStefano Zampini         PetscInt j,k;
322aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
323aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
324aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
32508122e43SStefano Zampini         }
32608122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
327aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
328aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
329aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
330aff50787SStefano Zampini           }
33108122e43SStefano Zampini         }
33208122e43SStefano Zampini       } else {
33308122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33408122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
33508122e43SStefano Zampini       }
3368bec7fa6SStefano Zampini     } else {
337f6f667cfSStefano Zampini       S = Sarray + cumarray;
338f6f667cfSStefano Zampini       St = Starray + cumarray;
3398bec7fa6SStefano Zampini     }
34008122e43SStefano Zampini 
341f6f667cfSStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
342aff50787SStefano Zampini     /* see if we can save some work */
343aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
344aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
345aff50787SStefano Zampini     }
346aff50787SStefano Zampini 
347aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
348aff50787SStefano Zampini       B_neigs = 0;
349aff50787SStefano Zampini     } else {
350aff50787SStefano Zampini       /* Threshold: this is an heuristic for edges */
351f6f667cfSStefano Zampini       thresh = pcbddc->mat_graph->count[idxs[0]]*pcbddc->adaptive_threshold;
352f6f667cfSStefano Zampini 
3539ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
35408122e43SStefano Zampini         PetscBLASInt B_itype = 1;
355f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
3564c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
3579552c7c7SStefano Zampini         PetscInt     nmin_s;
35808122e43SStefano Zampini 
359fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3608bec7fa6SStefano Zampini           PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %d/%d %d %d.\n",i,sub_schurs->n_subs,subset_size,pcbddc->mat_graph->count[idxs[0]]);
361fd14bc51SStefano Zampini         }
362d16cbb6bSStefano Zampini 
36308122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
364d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
365d16cbb6bSStefano Zampini 
366d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
36708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
368f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
36908122e43SStefano Zampini #else
370f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
37108122e43SStefano Zampini #endif
372d16cbb6bSStefano Zampini         } else {
373d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
374d16cbb6bSStefano Zampini           B_IL = 1;
375d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
376d16cbb6bSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
377d16cbb6bSStefano Zampini #else
378d16cbb6bSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
379d16cbb6bSStefano Zampini #endif
380d16cbb6bSStefano Zampini         }
38108122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
38208122e43SStefano Zampini         if (B_ierr) {
38308122e43SStefano Zampini           if (B_ierr < 0 ) {
38408122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
38508122e43SStefano Zampini           } else if (B_ierr <= B_N) {
38608122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
38708122e43SStefano Zampini           } else {
3889552c7c7SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1);
38908122e43SStefano Zampini           }
39008122e43SStefano Zampini         }
39108122e43SStefano Zampini 
39208122e43SStefano Zampini         if (B_neigs > nmax) {
393fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
394fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
395fd14bc51SStefano Zampini           }
396f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
39708122e43SStefano Zampini           B_neigs = nmax;
39808122e43SStefano Zampini         }
39908122e43SStefano Zampini 
4009552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
4019552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
40208122e43SStefano Zampini           PetscBLASInt B_neigs2;
40308122e43SStefano Zampini 
404f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
405f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
406fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
407fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, less than minimum required %d. Asking for %d to %d incl (fortran like)\n",B_neigs,nmin,B_IL,B_IU);
408fd14bc51SStefano Zampini           }
4099ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
41008122e43SStefano Zampini             PetscInt j;
41108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
41208122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
41308122e43SStefano Zampini             }
41408122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
41508122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
41608122e43SStefano Zampini             }
41708122e43SStefano Zampini           } else {
41808122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
41908122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
42008122e43SStefano Zampini           }
42108122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
423f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&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));
42408122e43SStefano Zampini #else
425f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&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));
42608122e43SStefano Zampini #endif
42708122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
42808122e43SStefano Zampini           B_neigs += B_neigs2;
42908122e43SStefano Zampini         }
43008122e43SStefano Zampini         if (B_ierr) {
43108122e43SStefano Zampini           if (B_ierr < 0 ) {
43208122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
43308122e43SStefano Zampini           } else if (B_ierr <= B_N) {
43408122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
43508122e43SStefano Zampini           } else {
4369552c7c7SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1);
43708122e43SStefano Zampini           }
43808122e43SStefano Zampini         }
439fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
440ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
44108122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
44208122e43SStefano Zampini             if (eigs[j] == 0.0) {
443ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
44408122e43SStefano Zampini             } else {
445ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
446fd14bc51SStefano Zampini             }
44708122e43SStefano Zampini           }
44808122e43SStefano Zampini         }
44908122e43SStefano Zampini       } else {
45008122e43SStefano Zampini           /* TODO */
45108122e43SStefano Zampini       }
452aff50787SStefano Zampini     }
4538bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
4548bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
4559162d606SStefano Zampini     if (B_neigs) {
4569162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
457fd14bc51SStefano Zampini 
458fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
4599552c7c7SStefano Zampini         PetscInt ii;
4609552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
461ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
4629552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
463ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
464ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
465ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
466ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
467ac47001eSStefano Zampini #else
468ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);CHKERRQ(ierr);
469ac47001eSStefano Zampini #endif
4709552c7c7SStefano Zampini           }
4719552c7c7SStefano Zampini         }
472fd14bc51SStefano Zampini       }
47308122e43SStefano Zampini #if 0
4749162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
47508122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
47608122e43SStefano Zampini         PetscScalar norm;
47708122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
4789162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
4799162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
48008122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
48108122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
48208122e43SStefano Zampini         } else {
48308122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
48408122e43SStefano Zampini         }
4859162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
486b1b3d7a2SStefano Zampini       }
487b1b3d7a2SStefano Zampini #endif
4889162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
4899162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
4909162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
4919162d606SStefano Zampini       cum++;
49208122e43SStefano Zampini     }
49308122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
49408122e43SStefano Zampini     /* shift for next computation */
49508122e43SStefano Zampini     cumarray += subset_size*subset_size;
49608122e43SStefano Zampini   }
497fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
498fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
499fd14bc51SStefano Zampini   }
50008122e43SStefano Zampini 
50108122e43SStefano Zampini   if (mss) {
50208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
50308122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
504f6f667cfSStefano Zampini     /* destroy matrices (junk) */
505f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
506f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
50708122e43SStefano Zampini   }
508f6f667cfSStefano Zampini   if (allocated_S_St) {
509f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
510f6f667cfSStefano Zampini   }
511f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
51208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
51308122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
51408122e43SStefano Zampini #endif
51508122e43SStefano Zampini   if (pcbddc->dbg_flag) {
5161b968477SStefano Zampini     PetscInt maxneigs_r;
51708122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5189b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
51908122e43SStefano Zampini   }
52008122e43SStefano Zampini   PetscFunctionReturn(0);
52108122e43SStefano Zampini }
522b1b3d7a2SStefano Zampini 
523674ae819SStefano Zampini #undef __FUNCT__
524c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
525c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
526c8587f34SStefano Zampini {
527c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5288629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
529c8587f34SStefano Zampini   PetscErrorCode ierr;
530c8587f34SStefano Zampini 
531c8587f34SStefano Zampini   PetscFunctionBegin;
532f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
5335e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
534c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
535c8587f34SStefano Zampini 
536684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
5370fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
538684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
539c8587f34SStefano Zampini 
540c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
541b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
542c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
543c8587f34SStefano Zampini   }
544c8587f34SStefano Zampini 
5458629588bSStefano Zampini   /*
5468629588bSStefano Zampini      Setup local correction and local part of coarse basis.
5478629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
5488629588bSStefano Zampini   */
54947f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
5508629588bSStefano Zampini 
5518629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
5528629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
5538629588bSStefano Zampini 
5548629588bSStefano Zampini   /* free */
5558629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
556c8587f34SStefano Zampini   PetscFunctionReturn(0);
557c8587f34SStefano Zampini }
558c8587f34SStefano Zampini 
559c8587f34SStefano Zampini #undef __FUNCT__
560674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
561674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
562674ae819SStefano Zampini {
563674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
564674ae819SStefano Zampini   PetscErrorCode ierr;
565674ae819SStefano Zampini 
566674ae819SStefano Zampini   PetscFunctionBegin;
567674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
568674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
569674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
570674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
571785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
572674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
573f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
574f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
575785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
57663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
57763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
578674ae819SStefano Zampini   PetscFunctionReturn(0);
579674ae819SStefano Zampini }
580674ae819SStefano Zampini 
581674ae819SStefano Zampini #undef __FUNCT__
582674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
583674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
584674ae819SStefano Zampini {
585674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
586674ae819SStefano Zampini   PetscErrorCode ierr;
587674ae819SStefano Zampini 
588674ae819SStefano Zampini   PetscFunctionBegin;
589b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
590674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
591674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
592674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
593b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
594674ae819SStefano Zampini   PetscFunctionReturn(0);
595674ae819SStefano Zampini }
596674ae819SStefano Zampini 
597674ae819SStefano Zampini #undef __FUNCT__
598674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
599674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
600674ae819SStefano Zampini {
601674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
60206656605SStefano Zampini   PetscScalar    *array;
603674ae819SStefano Zampini   PetscErrorCode ierr;
604674ae819SStefano Zampini 
605674ae819SStefano Zampini   PetscFunctionBegin;
606674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
60758da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
60806656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
60906656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
61058da7f69SStefano Zampini   }
611674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
612674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
61315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
61415aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
615674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
616674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
617674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
61806656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
619674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
620674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
6218ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
622674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
623674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
624674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
625f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
626f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
627f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
628f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
629727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
6300e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
631f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
63270cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
6336e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
63481d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
6350369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
6368b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
6378b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
63881d14e9dSStefano Zampini   ierr = PetscFree2(pcbddc->B0_cols,pcbddc->B0_vals);CHKERRQ(ierr);
639674ae819SStefano Zampini   PetscFunctionReturn(0);
640674ae819SStefano Zampini }
641674ae819SStefano Zampini 
642674ae819SStefano Zampini #undef __FUNCT__
643f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
644f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
6456bfb1811SStefano Zampini {
6466bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
6476bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
6486bfb1811SStefano Zampini   VecType        impVecType;
649019a44ceSStefano Zampini   PetscInt       n_constraints,n_R,old_size,n_benign;
6506bfb1811SStefano Zampini   PetscErrorCode ierr;
6516bfb1811SStefano Zampini 
6526bfb1811SStefano Zampini   PetscFunctionBegin;
653f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
654019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
655f4ddd8eeSStefano Zampini   }
656e7b262bdSStefano Zampini   /* get sizes */
657c9ed8603SStefano Zampini   n_benign = 0;
658c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) n_benign = 1;
659019a44ceSStefano Zampini   n_constraints = pcbddc->local_primal_size - n_benign - pcbddc->n_vertices;
660b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
6616bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
662e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
663e7b262bdSStefano Zampini   /* R nodes */
664e7b262bdSStefano Zampini   old_size = -1;
665e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
666e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
667e7b262bdSStefano Zampini   }
668e7b262bdSStefano Zampini   if (n_R != old_size) {
669e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
670e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
6716bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
6726bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
6736bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
6746bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
675e7b262bdSStefano Zampini   }
676e7b262bdSStefano Zampini   /* local primal dofs */
677e7b262bdSStefano Zampini   old_size = -1;
678e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
679e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
680e7b262bdSStefano Zampini   }
681e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
682e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
68383b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
684e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
6856bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
686e7b262bdSStefano Zampini   }
687e7b262bdSStefano Zampini   /* local explicit constraints */
688e7b262bdSStefano Zampini   old_size = -1;
689e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
690e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
691e7b262bdSStefano Zampini   }
692e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
693e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
69483b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
69583b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
69683b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
69783b7ccabSStefano Zampini   }
6986bfb1811SStefano Zampini   PetscFunctionReturn(0);
6996bfb1811SStefano Zampini }
7006bfb1811SStefano Zampini 
7016bfb1811SStefano Zampini #undef __FUNCT__
70247f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
70347f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
70488ebb749SStefano Zampini {
70525084f0cSStefano Zampini   PetscErrorCode  ierr;
70625084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
70788ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
70888ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
709d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
71025084f0cSStefano Zampini   /* submatrices of local problem */
71180677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
712019a44ceSStefano Zampini   /* submatrices of benign trick */
713d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
71406656605SStefano Zampini   /* submatrices of local coarse problem */
71506656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
71625084f0cSStefano Zampini   /* working matrices */
71706656605SStefano Zampini   Mat             C_CR;
71825084f0cSStefano Zampini   /* additional working stuff */
71906656605SStefano Zampini   PC              pc_R;
720d12edf2fSStefano Zampini   Mat             F,B0 = NULL;
72106656605SStefano Zampini   PetscBool       isLU,isCHOL,isILU;
72206656605SStefano Zampini 
72325084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
72406656605SStefano Zampini   PetscScalar     *work;
72506656605SStefano Zampini   PetscInt        *idx_V_B;
726d12edf2fSStefano Zampini   PetscInt        n,n_vertices,n_constraints,n_benign,p0_lidx_I = 0;
72706656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
728b9d89cd5SStefano Zampini   PetscBool       unsymmetric_check;
72945a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
73088ebb749SStefano Zampini   MatType         impMatType;
73125084f0cSStefano Zampini   /* some shortcuts to scalars */
73206656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
73388ebb749SStefano Zampini 
73488ebb749SStefano Zampini   PetscFunctionBegin;
735c9ed8603SStefano Zampini   n_benign = 0;
736c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) n_benign = 1;
737b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
738019a44ceSStefano Zampini   n_constraints = pcbddc->local_primal_size - n_benign - n_vertices;
73988ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
740b371cd4fSStefano Zampini   n_B = pcis->n_B;
741b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
74288ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
74388ebb749SStefano Zampini 
74488ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
74588ebb749SStefano Zampini   impMatType = MATSEQDENSE;
74688ebb749SStefano Zampini 
74788ebb749SStefano Zampini   /* vertices in boundary numbering */
748785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
7490e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
75088ebb749SStefano Zampini   if (i != n_vertices) {
75122d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
75288ebb749SStefano Zampini   }
75388ebb749SStefano Zampini 
75406656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
755019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
75606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
75706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
75806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
75906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
76006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
76106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
76206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
76306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
76406656605SStefano Zampini 
76506656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
76606656605SStefano Zampini   /* allocate workspace */
76706656605SStefano Zampini   n = 0;
76806656605SStefano Zampini   if (n_constraints) {
76906656605SStefano Zampini     n += n_R*n_constraints;
77006656605SStefano Zampini   }
77106656605SStefano Zampini   if (n_vertices) {
77206656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
77380677318SStefano Zampini     n = PetscMax((n_R+n_B)*n_vertices,n);
77406656605SStefano Zampini   }
7753301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
77606656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
77706656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
77806656605SStefano Zampini   }
77906656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
78006656605SStefano Zampini 
78106656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
78206656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
78306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
78406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
78506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
78606656605SStefano Zampini   if (isLU || isILU || isCHOL) {
78706656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
788d62866d3SStefano Zampini   } else if (sub_schurs->reuse_mumps) {
789d62866d3SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
790d62866d3SStefano Zampini     MatFactorType type;
791d62866d3SStefano Zampini 
7926816873aSStefano Zampini     F = reuse_mumps->F;
7936816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
794d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
79506656605SStefano Zampini   } else {
79606656605SStefano Zampini     F = NULL;
79706656605SStefano Zampini   }
79806656605SStefano Zampini 
79988ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
80088ebb749SStefano Zampini   if (n_constraints) {
80106656605SStefano Zampini     Mat         M1,M2,M3;
80280677318SStefano Zampini     Mat         auxmat;
80306656605SStefano Zampini     IS          is_aux;
80480677318SStefano Zampini     PetscScalar *array,*array2;
80506656605SStefano Zampini 
806f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
80780677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
80888ebb749SStefano Zampini 
80925084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
81025084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
8118ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
81280677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
81388ebb749SStefano Zampini 
81480677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
81580677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
81606656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
81788ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
81806656605SStefano Zampini       const PetscScalar *row_cmat_values;
81906656605SStefano Zampini       const PetscInt    *row_cmat_indices;
82006656605SStefano Zampini       PetscInt          size_of_constraint,j;
82188ebb749SStefano Zampini 
82206656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
82306656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
82406656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
82506656605SStefano Zampini       }
82606656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
82706656605SStefano Zampini     }
82880677318SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
82906656605SStefano Zampini     if (F) {
83006656605SStefano Zampini       Mat B;
83106656605SStefano Zampini 
83206656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
83380677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
83406656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
83506656605SStefano Zampini     } else {
83680677318SStefano Zampini       PetscScalar *marr;
83780677318SStefano Zampini 
83880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
83906656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
84006656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
84180677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*n_R);CHKERRQ(ierr);
84206656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
84306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
84406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
84506656605SStefano Zampini       }
84680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
84706656605SStefano Zampini     }
84880677318SStefano Zampini     if (!pcbddc->switch_static) {
84980677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
85080677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
85180677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
85280677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
85380677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*n_R);CHKERRQ(ierr);
85480677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
85580677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
85680677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
85780677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
85880677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
85980677318SStefano Zampini       }
86080677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
86180677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
86280677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
86380677318SStefano Zampini     } else {
86480677318SStefano Zampini       ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
86580677318SStefano Zampini       pcbddc->local_auxmat2 = local_auxmat2_R;
86625084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
86780677318SStefano Zampini     }
86880677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
86980677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
87080677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
87106656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
87206656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
87380677318SStefano Zampini     if (isCHOL) {
87480677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
87580677318SStefano Zampini     } else {
87625084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
87780677318SStefano Zampini     }
87880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
87906656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
88025084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
88125084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
88225084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
88380677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
88480677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
88580677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
88606656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
88706656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
888f4ddd8eeSStefano Zampini   }
88988ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
890d16cbb6bSStefano Zampini   if (n_benign) {
891d16cbb6bSStefano Zampini     IS        dummy;
892d16cbb6bSStefano Zampini     Mat       B0_R;
893d16cbb6bSStefano Zampini     PetscReal norm;
894d16cbb6bSStefano Zampini     PetscInt  ii[2];
895d16cbb6bSStefano Zampini 
896d16cbb6bSStefano Zampini     ii[0] = 0;
897d16cbb6bSStefano Zampini     ii[1] = pcbddc->B0_ncol;
898d16cbb6bSStefano Zampini     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,1,pcis->n,ii,pcbddc->B0_cols,pcbddc->B0_vals,&B0);CHKERRQ(ierr);
899d16cbb6bSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&dummy);CHKERRQ(ierr);
900d16cbb6bSStefano Zampini     ierr = MatGetSubMatrix(B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
901d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
902d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
903d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
904d16cbb6bSStefano Zampini     }
905d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
906d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
907d16cbb6bSStefano Zampini   }
908d16cbb6bSStefano Zampini 
90988ebb749SStefano Zampini   if (n_vertices) {
91006656605SStefano Zampini     IS is_aux;
9113a50541eSStefano Zampini 
9126816873aSStefano Zampini     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
9136816873aSStefano Zampini       IS tis;
9146816873aSStefano Zampini 
9156816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
9166816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
9176816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
9186816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
9196816873aSStefano Zampini     } else {
9203a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
9216816873aSStefano Zampini     }
9229577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
9239577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
92404708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
925019a44ceSStefano Zampini     if (n_benign) {
926019a44ceSStefano Zampini       IS dummy;
927019a44ceSStefano Zampini 
928019a44ceSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&dummy);CHKERRQ(ierr);
929019a44ceSStefano Zampini       ierr = MatGetSubMatrix(B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
930019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
931019a44ceSStefano Zampini     }
93225084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
93388ebb749SStefano Zampini   }
93488ebb749SStefano Zampini 
93588ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
936f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
93706656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
93806656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
93906656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
94006656605SStefano Zampini     }
941f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
94206656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
94306656605SStefano Zampini       PetscScalar *marray;
94406656605SStefano Zampini 
94506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
94606656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
947f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
948f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
949f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
950f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
951f4ddd8eeSStefano Zampini     }
952f4ddd8eeSStefano Zampini   }
95306656605SStefano Zampini 
954f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
95506656605SStefano Zampini     PetscScalar *marray;
95688ebb749SStefano Zampini 
95706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
9588eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
95906656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
96088ebb749SStefano Zampini     }
9613301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
96206656605SStefano Zampini       n *= 2;
96388ebb749SStefano Zampini     }
96406656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
96506656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
96606656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
9678eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
96806656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
96906656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
97088ebb749SStefano Zampini     }
9713301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
97206656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
9738eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
97406656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
97506656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
97688ebb749SStefano Zampini       }
97788ebb749SStefano Zampini     } else {
978c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
979c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
9801b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
981c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
982c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
983c0553b1fSStefano Zampini       }
98488ebb749SStefano Zampini     }
98506656605SStefano Zampini   }
986019a44ceSStefano Zampini 
98706656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
988d12edf2fSStefano Zampini   if (n_benign && (pcbddc->switch_static || pcbddc->dbg_flag)) {
989d12edf2fSStefano Zampini     const PetscInt *idxs;
990d12edf2fSStefano Zampini 
991d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
992d12edf2fSStefano Zampini     ierr = PetscFindInt(pcbddc->benign_p0_lidx,pcis->n-pcis->n_B,idxs,&p0_lidx_I);CHKERRQ(ierr);
993d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
994d12edf2fSStefano Zampini   }
995d16cbb6bSStefano Zampini 
99606656605SStefano Zampini   /* vertices */
99706656605SStefano Zampini   if (n_vertices) {
99816f15bc4SStefano Zampini 
99904708bb6SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
100004708bb6SStefano Zampini 
100116f15bc4SStefano Zampini     if (n_R) {
100206656605SStefano Zampini       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
100306656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
100416f15bc4SStefano Zampini       PetscScalar  *x,*y;
100504708bb6SStefano Zampini       PetscBool    isseqaij;
100606656605SStefano Zampini 
100721eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
100806656605SStefano Zampini       ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
100904708bb6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
10106816873aSStefano Zampini       if (F) { /* TODO could be optimized for symmetric problems */
101106656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
101206656605SStefano Zampini       } else {
101306656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
101406656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
101506656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
101606656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
101706656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
101806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
101906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
102006656605SStefano Zampini         }
102106656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
102206656605SStefano Zampini       }
102380677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
102406656605SStefano Zampini       /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
102506656605SStefano Zampini       if (n_constraints) {
102606656605SStefano Zampini         Mat B;
102780677318SStefano Zampini 
1028b3d85658SStefano Zampini         ierr = PetscMemzero(work+n_R*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
102980677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
103080677318SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
103180677318SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+n_R*n_vertices+i*n_B);CHKERRQ(ierr);
103280677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
103380677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
103480677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
103580677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
103680677318SStefano Zampini         }
103780677318SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
103880677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
103980677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
104006656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
104180677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
104206656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
104306656605SStefano Zampini         ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
104406656605SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
104506656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
104606656605SStefano Zampini       }
104704708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
104804708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
104904708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
105004708bb6SStefano Zampini       }
105106656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
105280677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
105306656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
105406656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
105506656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
105606656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
105706656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
105806656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
105906656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1060d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1061019a44ceSStefano Zampini     } else {
1062d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1063d16cbb6bSStefano Zampini     }
1064d16cbb6bSStefano Zampini     if (n_benign) {
1065019a44ceSStefano Zampini       const PetscScalar *vals;
1066019a44ceSStefano Zampini       const PetscInt    *idxs;
1067019a44ceSStefano Zampini       PetscInt          n,j;
1068019a44ceSStefano Zampini 
1069019a44ceSStefano Zampini       ierr = MatGetRow(B0_V,0,&n,&idxs,&vals);CHKERRQ(ierr);
1070d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
1071d16cbb6bSStefano Zampini         coarse_submat_vals[(pcbddc->local_primal_size-1)*pcbddc->local_primal_size+idxs[j]] = vals[j];
1072d16cbb6bSStefano Zampini         coarse_submat_vals[(idxs[j]+1)*pcbddc->local_primal_size-1] = vals[j];
1073019a44ceSStefano Zampini       }
1074019a44ceSStefano Zampini       ierr = MatRestoreRow(B0_V,0,&n,&idxs,&vals);CHKERRQ(ierr);
107516f15bc4SStefano Zampini     }
107621eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1077d16cbb6bSStefano Zampini 
107806656605SStefano Zampini     /* coarse basis functions */
107906656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
108016f15bc4SStefano Zampini       PetscScalar *y;
108116f15bc4SStefano Zampini 
108206656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
108306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
108406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
108506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
108606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
108706656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
108806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
108906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
109006656605SStefano Zampini 
109106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
109206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
109306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
109406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
109506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
109606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1097a0aff763SStefano Zampini         if (n_benign) y[n_D*i+p0_lidx_I] = 0.0;
109806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
109906656605SStefano Zampini       }
110006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
110106656605SStefano Zampini     }
110204708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
110304708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
110406656605SStefano Zampini   }
110506656605SStefano Zampini 
110606656605SStefano Zampini   if (n_constraints) {
110706656605SStefano Zampini     Mat B;
110806656605SStefano Zampini 
110906656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
111006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
111180677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
111206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
111306656605SStefano Zampini     if (n_vertices) {
111480677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
111580677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
111680677318SStefano Zampini       } else {
111780677318SStefano Zampini         Mat S_VCt;
111880677318SStefano Zampini 
111980677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
112080677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
112180677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
112280677318SStefano Zampini       }
112306656605SStefano Zampini     }
112406656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
112506656605SStefano Zampini     /* coarse basis functions */
112606656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
112706656605SStefano Zampini       PetscScalar *y;
112806656605SStefano Zampini 
112906656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
113006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
113106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
113206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
113306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
113406656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
113506656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
113606656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
113706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
113806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
113906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
114006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
114106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1142d16cbb6bSStefano Zampini         if (n_benign) y[n_D*(i+n_vertices)+p0_lidx_I] = 0.0;
114306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
114406656605SStefano Zampini       }
114506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
114606656605SStefano Zampini     }
114706656605SStefano Zampini   }
114880677318SStefano Zampini   if (n_constraints) {
114980677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
115080677318SStefano Zampini   }
115106656605SStefano Zampini 
1152019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1153019a44ceSStefano Zampini 
115406656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
11553301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
115606656605SStefano Zampini 
115706656605SStefano Zampini     if (n_constraints) {
115816f15bc4SStefano Zampini       Mat S_CCT,B_C;
115906656605SStefano Zampini 
116080677318SStefano Zampini       /* this is a lazy thing */
116180677318SStefano Zampini       ierr = MatConvert(C_CR,impMatType,MAT_REUSE_MATRIX,&C_CR);CHKERRQ(ierr);
116206656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
116306656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
116406656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
116516f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
116606656605SStefano Zampini       if (n_vertices) {
116716f15bc4SStefano Zampini         Mat B_V,S_VCT;
116806656605SStefano Zampini 
116906656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
117006656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
117106656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
117206656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
117316f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
117406656605SStefano Zampini       }
117506656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
117680677318SStefano Zampini     } else { /* if there are no constraints, reset work */
117780677318SStefano Zampini       ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
117806656605SStefano Zampini     }
117916f15bc4SStefano Zampini     if (n_vertices && n_R) {
118006656605SStefano Zampini       Mat          A_VRT;
118180677318SStefano Zampini       PetscScalar  *marray;
118206656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
118306656605SStefano Zampini 
118480677318SStefano Zampini       ierr = MatTranspose(A_VR,MAT_INITIAL_MATRIX,&A_VRT);CHKERRQ(ierr);
118580677318SStefano Zampini       ierr = MatConvert(A_VRT,impMatType,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
118680677318SStefano Zampini       ierr = MatDenseGetArray(A_VRT,&marray);CHKERRQ(ierr);
118706656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
118880677318SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,marray,&B_one,work,&B_one));
118980677318SStefano Zampini       ierr = MatDenseRestoreArray(A_VRT,&marray);CHKERRQ(ierr);
119016f15bc4SStefano Zampini       ierr = MatDestroy(&A_VRT);CHKERRQ(ierr);
119106656605SStefano Zampini     }
119206656605SStefano Zampini 
119306656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
119406656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
119506656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
119606656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
119706656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
119806656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
119906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
120006656605SStefano Zampini       }
120106656605SStefano Zampini     } else {
120206656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
120306656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
120406656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
120506656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
120606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
120706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
120806656605SStefano Zampini       }
120906656605SStefano Zampini     }
121006656605SStefano Zampini     /* coarse basis functions */
121106656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
121206656605SStefano Zampini       PetscScalar *y;
121306656605SStefano Zampini 
121406656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
121506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
121606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
121706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
121806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
121906656605SStefano Zampini       if (i<n_vertices) {
122006656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
122106656605SStefano Zampini       }
122206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
122306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
122406656605SStefano Zampini 
122506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
122606656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
122706656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
122806656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
122906656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
123006656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
123106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
123206656605SStefano Zampini       }
123306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
123406656605SStefano Zampini     }
123506656605SStefano Zampini   }
1236d62866d3SStefano Zampini   /* free memory */
123788ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
123806656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
123906656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
124006656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
124106656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
1242d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
1243d62866d3SStefano Zampini   if (n_vertices) {
1244d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1245d62866d3SStefano Zampini   }
1246d62866d3SStefano Zampini   if (n_constraints) {
1247d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1248d62866d3SStefano Zampini   }
124988ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
125088ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
125188ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1252d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
125388ebb749SStefano Zampini     Mat         coarse_sub_mat;
125425084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
125588ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
125688ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
125788ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
12588bec7fa6SStefano Zampini     Mat         C_B,CPHI;
12598bec7fa6SStefano Zampini     IS          is_dummy;
12608bec7fa6SStefano Zampini     Vec         mones;
126188ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
126288ebb749SStefano Zampini     PetscReal   real_value;
126388ebb749SStefano Zampini 
126488ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
126588ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
126688ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
126788ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
126888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
126988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1270c0553b1fSStefano Zampini     if (unsymmetric_check) {
127188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
127288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
127388ebb749SStefano Zampini     }
127488ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
127588ebb749SStefano Zampini 
127625084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
12773301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
127825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1279c0553b1fSStefano Zampini     if (unsymmetric_check) {
128088ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
128188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
128288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
128388ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
128488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
128588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
128688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
128788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
128888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
128988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
129088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
129188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
129288ebb749SStefano Zampini     } else {
129388ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
129488ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
129588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
129688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
129788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
129888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
129988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
130088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
130188ebb749SStefano Zampini     }
130288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
130388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
130488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
130588ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
1306d12edf2fSStefano Zampini     if (n_benign) {
1307d12edf2fSStefano Zampini       Mat B0_I,B0_B,B0_BPHI,B0_IPHI;
1308d12edf2fSStefano Zampini       PetscScalar *data,*data2;
1309d12edf2fSStefano Zampini 
1310d12edf2fSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&is_dummy);CHKERRQ(ierr);
1311d12edf2fSStefano Zampini       ierr = MatGetSubMatrix(B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
1312d12edf2fSStefano Zampini       ierr = MatGetSubMatrix(B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
1313d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
1314d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
1315d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
1316d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
1317d12edf2fSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
1318d16cbb6bSStefano Zampini         data[(pcbddc->local_primal_size-1)*pcbddc->local_primal_size+i] += data2[i];
1319d16cbb6bSStefano Zampini         data[(i+1)*pcbddc->local_primal_size-1] += data2[i];
1320d12edf2fSStefano Zampini       }
1321d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
1322d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
1323d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
1324d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1325d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
1326d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
1327d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
1328d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1329d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
1330d12edf2fSStefano Zampini     }
1331d12edf2fSStefano Zampini #if 0
1332d12edf2fSStefano Zampini   {
1333d12edf2fSStefano Zampini     PetscViewer viewer;
1334d12edf2fSStefano Zampini     char filename[256];
1335d12edf2fSStefano Zampini     sprintf(filename,"proj_local_coarse_mat%d.m",PetscGlobalRank);
1336d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1337d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1338d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
1339d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1340d12edf2fSStefano Zampini   }
1341d12edf2fSStefano Zampini #endif
134281d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
13438bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
13440fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
134506656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
13468bec7fa6SStefano Zampini 
13478bec7fa6SStefano Zampini     /* check constraints */
1348d12edf2fSStefano Zampini     if (!n_benign) {
13498bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
13508bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
13518bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
13528bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
13538bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
13548bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
13558bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1356bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1357c0553b1fSStefano Zampini       if (unsymmetric_check) {
1358bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1359bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1360bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1361bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1362bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
136388ebb749SStefano Zampini       }
13648bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
13658bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
13668bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
13678bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
1368d12edf2fSStefano Zampini     }
136925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
137088ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
137188ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
137288ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
137388ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
137488ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
137588ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
137688ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
137788ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
137888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
137988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1380c0553b1fSStefano Zampini     if (unsymmetric_check) {
138188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
138288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
138388ebb749SStefano Zampini     }
138488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
138588ebb749SStefano Zampini   }
1386d12edf2fSStefano Zampini   ierr = MatDestroy(&B0);CHKERRQ(ierr);
13878629588bSStefano Zampini   /* get back data */
13888629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
138988ebb749SStefano Zampini   PetscFunctionReturn(0);
139088ebb749SStefano Zampini }
139188ebb749SStefano Zampini 
139288ebb749SStefano Zampini #undef __FUNCT__
1393d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1394d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
1395aa0d41d4SStefano Zampini {
1396d65f70fdSStefano Zampini   Mat            *work_mat;
1397d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1398d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1399d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1400aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1401aa0d41d4SStefano Zampini 
1402aa0d41d4SStefano Zampini   PetscFunctionBegin;
1403d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1404d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1405d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1406d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1407aa0d41d4SStefano Zampini 
1408d65f70fdSStefano Zampini   if (!rsorted) {
1409906d46d4SStefano Zampini     const PetscInt *idxs;
1410906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
1411aa0d41d4SStefano Zampini 
1412d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1413d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1414d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1415d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1416aa0d41d4SStefano Zampini     }
1417d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1418d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1419d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1420d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1421aa0d41d4SStefano Zampini     }
1422d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1423d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1424d65f70fdSStefano Zampini   } else {
1425d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1426d65f70fdSStefano Zampini     isrow_s = isrow;
1427aa0d41d4SStefano Zampini   }
1428906d46d4SStefano Zampini 
1429d65f70fdSStefano Zampini   if (!csorted) {
1430d65f70fdSStefano Zampini     if (isrow == iscol) {
1431d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1432d65f70fdSStefano Zampini       iscol_s = isrow_s;
1433d65f70fdSStefano Zampini     } else {
1434d65f70fdSStefano Zampini       const PetscInt *idxs;
1435d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1436906d46d4SStefano Zampini 
1437d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1438d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1439d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1440d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1441d65f70fdSStefano Zampini       }
1442d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1443d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1444d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1445d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1446d65f70fdSStefano Zampini       }
1447d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1448d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1449d65f70fdSStefano Zampini     }
1450d65f70fdSStefano Zampini   } else {
1451d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1452d65f70fdSStefano Zampini     iscol_s = iscol;
1453d65f70fdSStefano Zampini   }
1454d65f70fdSStefano Zampini 
1455d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1456d65f70fdSStefano Zampini 
1457d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1458906d46d4SStefano Zampini     Mat      new_mat;
1459d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1460906d46d4SStefano Zampini 
1461d65f70fdSStefano Zampini     if (!rsorted) {
1462d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1463d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1464d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1465d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1466906d46d4SStefano Zampini       }
1467d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1468d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1469d65f70fdSStefano Zampini     } else {
1470d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1471906d46d4SStefano Zampini     }
1472d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1473d65f70fdSStefano Zampini 
1474d65f70fdSStefano Zampini     if (!csorted) {
1475d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1476d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1477d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1478d65f70fdSStefano Zampini       } else {
1479d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1480d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1481d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1482d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1483d65f70fdSStefano Zampini         }
1484d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1485d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1486d65f70fdSStefano Zampini       }
1487d65f70fdSStefano Zampini     } else {
1488d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1489d65f70fdSStefano Zampini     }
1490d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1491d65f70fdSStefano Zampini 
1492d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1493d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1494d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1495d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1496d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1497d65f70fdSStefano Zampini   }
1498d65f70fdSStefano Zampini 
1499d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1500d65f70fdSStefano Zampini   *B = work_mat[0];
1501d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1502d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1503d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1504d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1505d65f70fdSStefano Zampini }
1506d65f70fdSStefano Zampini 
1507d65f70fdSStefano Zampini #undef __FUNCT__
15085e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
15095e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1510aa0d41d4SStefano Zampini {
1511aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
15125e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1513d65f70fdSStefano Zampini   Mat            new_mat;
15145e8657edSStefano Zampini   IS             is_local,is_global;
1515d65f70fdSStefano Zampini   PetscInt       local_size;
1516d65f70fdSStefano Zampini   PetscBool      isseqaij;
1517aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1518aa0d41d4SStefano Zampini 
1519aa0d41d4SStefano Zampini   PetscFunctionBegin;
1520aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
15215e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
15225e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1523b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
1524aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1525d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
1526aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1527906d46d4SStefano Zampini 
1528906d46d4SStefano Zampini   /* check */
1529906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
1530906d46d4SStefano Zampini     Vec       x,x_change;
1531906d46d4SStefano Zampini     PetscReal error;
1532906d46d4SStefano Zampini 
15335e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1534906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
15355e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
1536e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1537e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1538d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
1539e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1540e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1541906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1542906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1543906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1544906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1545906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
1546906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1547906d46d4SStefano Zampini   }
1548906d46d4SStefano Zampini 
154922d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
15509b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
155122d5777bSStefano Zampini   if (isseqaij) {
1552d65f70fdSStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1553aa0d41d4SStefano Zampini   } else {
1554aa0d41d4SStefano Zampini     Mat work_mat;
1555aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1556d65f70fdSStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1557aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
1558aa0d41d4SStefano Zampini   }
15593301b35fSStefano Zampini   if (matis->A->symmetric_set) {
15603301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
1561e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
15623301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
1563e496cd5dSStefano Zampini #endif
15643301b35fSStefano Zampini   }
156545a1bb75SStefano Zampini   /*
156645a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1567d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
156845a1bb75SStefano Zampini   */
1569d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
1570aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
1571aa0d41d4SStefano Zampini }
1572aa0d41d4SStefano Zampini 
1573aa0d41d4SStefano Zampini #undef __FUNCT__
1574a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
15758ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
1576a64d13efSStefano Zampini {
1577a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
1578a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1579d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
158053892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
15813a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
15823a50541eSStefano Zampini   PetscInt        vbs,bs;
15836816873aSStefano Zampini   PetscBT         bitmask=NULL;
1584a64d13efSStefano Zampini   PetscErrorCode  ierr;
1585a64d13efSStefano Zampini 
1586a64d13efSStefano Zampini   PetscFunctionBegin;
1587b23d619eSStefano Zampini   /*
1588b23d619eSStefano Zampini     No need to setup local scatters if
1589b23d619eSStefano Zampini       - primal space is unchanged
1590b23d619eSStefano Zampini         AND
1591b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
1592b23d619eSStefano Zampini         AND
1593b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
1594b23d619eSStefano Zampini   */
1595b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
1596f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
1597f4ddd8eeSStefano Zampini   }
1598f4ddd8eeSStefano Zampini   /* destroy old objects */
1599f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1600f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1601f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1602a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
1603b371cd4fSStefano Zampini   n_B = pcis->n_B;
1604b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
1605b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
16063a50541eSStefano Zampini 
1607a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
16086816873aSStefano Zampini 
160953892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
16106816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
1611854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
1612a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
1613a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
16140e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
1615a64d13efSStefano Zampini     }
1616a64d13efSStefano Zampini 
1617a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
16184641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
16196816873aSStefano Zampini         idx_R_local[n_R++] = i;
1620a64d13efSStefano Zampini       }
1621a64d13efSStefano Zampini     }
162253892102SStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
16236816873aSStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
16246816873aSStefano Zampini 
162553892102SStefano Zampini     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
162653892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
16276816873aSStefano Zampini   }
16283a50541eSStefano Zampini 
16293a50541eSStefano Zampini   /* Block code */
16303a50541eSStefano Zampini   vbs = 1;
16313a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
16323a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
16333a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
16343a50541eSStefano Zampini     PetscInt  *vary;
1635d3df7717SStefano Zampini     if (!sub_schurs->reuse_mumps) {
1636785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
16373a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
1638d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
1639d3df7717SStefano 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 */
16400e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
1641d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
16423a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
16433a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
16443a50541eSStefano Zampini           break;
16453a50541eSStefano Zampini         }
16463a50541eSStefano Zampini       }
1647d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
1648d3df7717SStefano Zampini     } else {
1649d3df7717SStefano Zampini       /* Verify directly the R set */
1650d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
1651d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
1652d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
1653d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
1654d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
1655d3df7717SStefano Zampini             break;
1656d3df7717SStefano Zampini           }
1657d3df7717SStefano Zampini         }
1658d3df7717SStefano Zampini       }
1659d3df7717SStefano Zampini     }
16603a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
16613a50541eSStefano Zampini       vbs = bs;
16623a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
16633a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
16643a50541eSStefano Zampini       }
16653a50541eSStefano Zampini     }
16663a50541eSStefano Zampini   }
16673a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
166853892102SStefano Zampini   if (sub_schurs->reuse_mumps) {
166953892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
167053892102SStefano Zampini 
167153892102SStefano Zampini     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
167253892102SStefano Zampini     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
167353892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
167453892102SStefano Zampini     reuse_mumps->is_R = pcbddc->is_R_local;
167553892102SStefano Zampini   } else {
16763a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
167753892102SStefano Zampini   }
1678a64d13efSStefano Zampini 
1679a64d13efSStefano Zampini   /* print some info if requested */
1680a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
1681c9ed8603SStefano Zampini     PetscInt benign = 0;
1682019a44ceSStefano Zampini 
1683c9ed8603SStefano Zampini     if (pcbddc->benign_p0_lidx >= 0) benign = 1;
1684a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1685a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
16860fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1687a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1688a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
1689019a44ceSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,n_vertices,pcbddc->local_primal_size-n_vertices-benign,pcbddc->local_primal_size);CHKERRQ(ierr);
1690a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1691a64d13efSStefano Zampini   }
1692a64d13efSStefano Zampini 
1693a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
16946816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
16956816873aSStefano Zampini     IS       is_aux1,is_aux2;
16966816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
16976816873aSStefano Zampini 
16983a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1699854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
1700854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
1701a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
17024641a718SStefano Zampini     for (i=0; i<n_D; i++) {
17034641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
17044641a718SStefano Zampini     }
1705a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1706a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
17074641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
17084641a718SStefano Zampini         aux_array1[j++] = i;
1709a64d13efSStefano Zampini       }
1710a64d13efSStefano Zampini     }
1711a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1712a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1713a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
17144641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
17154641a718SStefano Zampini         aux_array2[j++] = i;
1716a64d13efSStefano Zampini       }
1717a64d13efSStefano Zampini     }
1718a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1719a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
1720a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1721a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1722a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1723a64d13efSStefano Zampini 
17248eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
1725785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
1726a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
17274641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
17284641a718SStefano Zampini           aux_array1[j++] = i;
1729a64d13efSStefano Zampini         }
1730a64d13efSStefano Zampini       }
1731a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1732a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1733a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1734a64d13efSStefano Zampini     }
17354641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
17363a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1737d62866d3SStefano Zampini   } else {
173853892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
17396816873aSStefano Zampini     IS               tis;
17406816873aSStefano Zampini     PetscInt         schur_size;
17416816873aSStefano Zampini 
174253892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
17436816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
174453892102SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
17456816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
17466816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
17476816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
17486816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
17496816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
1750d62866d3SStefano Zampini     }
1751d62866d3SStefano Zampini   }
1752a64d13efSStefano Zampini   PetscFunctionReturn(0);
1753a64d13efSStefano Zampini }
1754a64d13efSStefano Zampini 
1755304d26faSStefano Zampini 
1756304d26faSStefano Zampini #undef __FUNCT__
1757304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1758684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1759304d26faSStefano Zampini {
1760304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1761304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1762304d26faSStefano Zampini   PC             pc_temp;
1763304d26faSStefano Zampini   Mat            A_RR;
1764f4ddd8eeSStefano Zampini   MatReuse       reuse;
1765304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1766304d26faSStefano Zampini   PetscReal      value;
176704708bb6SStefano Zampini   PetscInt       n_D,n_R;
17689577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1769304d26faSStefano Zampini   PetscErrorCode ierr;
1770e604994aSStefano Zampini   /* prefixes stuff */
1771312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1772e604994aSStefano Zampini   size_t         len;
1773304d26faSStefano Zampini 
1774304d26faSStefano Zampini   PetscFunctionBegin;
1775304d26faSStefano Zampini 
1776e604994aSStefano Zampini   /* compute prefixes */
1777e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1778e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1779e604994aSStefano Zampini   if (!pcbddc->current_level) {
1780e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1781e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1782e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1783e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1784e604994aSStefano Zampini   } else {
1785e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1786312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1787e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1788e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1789312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1790312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
179134d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
179234d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1793e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1794e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1795e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1796e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1797e604994aSStefano Zampini   }
1798e604994aSStefano Zampini 
1799304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1800684f6988SStefano Zampini   if (dirichlet) {
1801d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
18023301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
18033301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
1804964fefecSStefano Zampini     }
1805ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
1806964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
1807304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1808304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1809304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1810304d26faSStefano Zampini       /* default */
1811304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1812e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
18139577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1814304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
18159577ea80SStefano Zampini       if (issbaij) {
18169577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
18179577ea80SStefano Zampini       } else {
1818304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
18199577ea80SStefano Zampini       }
1820304d26faSStefano Zampini       /* Allow user's customization */
1821304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1822304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1823304d26faSStefano Zampini     }
1824d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1825d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
1826d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1827d62866d3SStefano Zampini 
1828d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
1829d5574798SStefano Zampini     }
1830304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1831304d26faSStefano Zampini     if (!n_D) {
1832304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1833304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1834304d26faSStefano Zampini     }
1835304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1836304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1837304d26faSStefano Zampini     /* set ksp_D into pcis data */
1838304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1839304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1840304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1841684f6988SStefano Zampini   }
1842304d26faSStefano Zampini 
1843304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1844684f6988SStefano Zampini   A_RR = 0;
1845684f6988SStefano Zampini   if (neumann) {
1846d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
184704708bb6SStefano Zampini     PetscInt        ibs,mbs;
184804708bb6SStefano Zampini     PetscBool       issbaij;
184904708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
1850f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
18518ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1852f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1853f4ddd8eeSStefano Zampini       PetscInt nn_R;
185481d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1855f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1856f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1857f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1858f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1859f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1860f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1861f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1862727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1863f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1864f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1865f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1866f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1867f4ddd8eeSStefano Zampini         }
1868f4ddd8eeSStefano Zampini       }
1869f4ddd8eeSStefano Zampini       /* last check */
1870d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1871f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1872f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1873f4ddd8eeSStefano Zampini       }
1874f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1875f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1876f4ddd8eeSStefano Zampini     }
1877f4ddd8eeSStefano Zampini     /* extract A_RR */
1878af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1879af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
188004708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
188104708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
188204708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
188304708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
188404708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
1885af732b37SStefano Zampini       } else {
188604708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
18876816873aSStefano Zampini       }
188804708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
188904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
189004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
189104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
189204708bb6SStefano Zampini       } else {
189304708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
189404708bb6SStefano Zampini       }
189504708bb6SStefano Zampini     }
189604708bb6SStefano Zampini     if (!sub_schurs->reuse_mumps) {
1897f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
18983301b35fSStefano Zampini       if (pcbddc->local_mat->symmetric_set) {
18993301b35fSStefano Zampini         ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
19006816873aSStefano Zampini       }
19016816873aSStefano Zampini     } else {
19026816873aSStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
19036816873aSStefano Zampini 
19046816873aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
19056816873aSStefano Zampini       ierr = PCGetOperators(reuse_mumps->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
19066816873aSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1907af732b37SStefano Zampini     }
1908f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
1909304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1910304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1911304d26faSStefano Zampini       /* default */
1912304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1913e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
1914304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
19159577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
19169577ea80SStefano Zampini       if (issbaij) {
19179577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
19189577ea80SStefano Zampini       } else {
1919304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
19209577ea80SStefano Zampini       }
1921304d26faSStefano Zampini       /* Allow user's customization */
1922304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1923304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1924304d26faSStefano Zampini     }
1925d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
1926304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1927304d26faSStefano Zampini     if (!n_R) {
1928304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1929304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1930304d26faSStefano Zampini     }
1931d62866d3SStefano Zampini     /* Reuse MUMPS solver if it is present */
1932d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
1933d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1934d62866d3SStefano Zampini 
1935d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
1936d62866d3SStefano Zampini     }
1937304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
1938304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1939684f6988SStefano Zampini   }
19406816873aSStefano Zampini   /* free Neumann problem's matrix */
19416816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1942304d26faSStefano Zampini 
1943304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
19440fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
1945684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
1946684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1947684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1948684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1949684f6988SStefano Zampini     }
1950684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
19510fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
19520fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
19530fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
19540fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
19550fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
1956304d26faSStefano Zampini       /* need to be adapted? */
1957b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1958b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1959b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
1960304d26faSStefano Zampini       /* print info */
1961304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1962e604994aSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Dirichlet solve (%s) = % 1.14e \n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_D))->prefix,value);CHKERRQ(ierr);
1963304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1964304d26faSStefano Zampini       }
1965b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
1966298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
1967304d26faSStefano Zampini       }
1968684f6988SStefano Zampini     }
1969684f6988SStefano Zampini     if (neumann) { /* Neumann */
19706816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
19710fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
19720fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
19730fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
19740fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
19750fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
1976304d26faSStefano Zampini       /* need to be adapted? */
1977b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1978b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1979304d26faSStefano Zampini       /* print info */
1980304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1981e604994aSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Neumann solve (%s) = % 1.14e\n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_R))->prefix,value);CHKERRQ(ierr);
1982304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1983304d26faSStefano Zampini       }
1984b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
1985298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
1986304d26faSStefano Zampini       }
19870fccc4e9SStefano Zampini     }
1988684f6988SStefano Zampini   }
1989304d26faSStefano Zampini   PetscFunctionReturn(0);
1990304d26faSStefano Zampini }
1991304d26faSStefano Zampini 
1992304d26faSStefano Zampini #undef __FUNCT__
1993ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
199480677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
1995674ae819SStefano Zampini {
1996674ae819SStefano Zampini   PetscErrorCode  ierr;
1997674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1998be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
1999674ae819SStefano Zampini 
2000674ae819SStefano Zampini   PetscFunctionBegin;
2001be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
200280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
200320c7b377SStefano Zampini   }
200480677318SStefano Zampini   if (!pcbddc->switch_static) {
200580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
200680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
200780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
200820c7b377SStefano Zampini     }
2009be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
201080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
201180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
201220c7b377SStefano Zampini     } else {
2013be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2014be83ff47SStefano Zampini 
201553892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201653892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201720c7b377SStefano Zampini     }
2018be83ff47SStefano Zampini   } else {
201980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202380677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
202480677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
202580677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
202680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2028674ae819SStefano Zampini     }
2029674ae819SStefano Zampini   }
2030be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
203180677318SStefano Zampini     if (applytranspose) {
203280677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
203380677318SStefano Zampini     } else {
203480677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
203580677318SStefano Zampini     }
203653892102SStefano Zampini #if defined(PETSC_HAVE_MUMPS)
2037be83ff47SStefano Zampini   } else {
2038be83ff47SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2039be83ff47SStefano Zampini 
2040be83ff47SStefano Zampini     if (applytranspose) {
204153892102SStefano Zampini       ierr = MatMumpsSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2042be83ff47SStefano Zampini     } else {
204353892102SStefano Zampini       ierr = MatMumpsSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2044be83ff47SStefano Zampini     }
204553892102SStefano Zampini #endif
2046be83ff47SStefano Zampini   }
204780677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
204880677318SStefano Zampini   if (!pcbddc->switch_static) {
2049be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
205080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
205180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2052be83ff47SStefano Zampini     } else {
2053be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2054be83ff47SStefano Zampini 
205553892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
205653892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2057be83ff47SStefano Zampini     }
205880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
205980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
206080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
206180677318SStefano Zampini     }
206280677318SStefano Zampini   } else {
206380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
206480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
206580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
206680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
206780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
206880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
206980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
207080677318SStefano Zampini     }
207180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
207280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
207380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
207480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2075674ae819SStefano Zampini   }
2076674ae819SStefano Zampini   PetscFunctionReturn(0);
2077674ae819SStefano Zampini }
2078674ae819SStefano Zampini 
2079dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2080674ae819SStefano Zampini #undef __FUNCT__
2081674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2082dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2083674ae819SStefano Zampini {
2084674ae819SStefano Zampini   PetscErrorCode ierr;
2085674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2086674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2087674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2088674ae819SStefano Zampini 
2089674ae819SStefano Zampini   PetscFunctionBegin;
2090dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2091dc359a40SStefano Zampini   if (applytranspose) {
2092674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
20938eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2094dc359a40SStefano Zampini   } else {
2095674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2096674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
209715aaf578SStefano Zampini   }
2098efc2fbd9SStefano Zampini 
2099efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
2100c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
2101efc2fbd9SStefano Zampini     PetscScalar *array;
2102efc2fbd9SStefano Zampini 
2103efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2104efc2fbd9SStefano Zampini     array[pcbddc->local_primal_size-1] += pcbddc->benign_p0;
2105efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2106efc2fbd9SStefano Zampini   }
2107efc2fbd9SStefano Zampini 
210812edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
210912edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
211012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211212edc857SStefano Zampini 
21139f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
211412edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
211512edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
2116964fefecSStefano Zampini     Vec rhs,sol;
2117964fefecSStefano Zampini 
2118964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2119964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
212012edc857SStefano Zampini     if (applytranspose) {
2121964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
212212edc857SStefano Zampini     } else {
2123964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
212412edc857SStefano Zampini     }
212512edc857SStefano Zampini   }
2126674ae819SStefano Zampini 
2127674ae819SStefano Zampini   /* Local solution on R nodes */
212880677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
212980677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
21309f00e9b4SStefano Zampini   }
2131674ae819SStefano Zampini 
21329f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
21339f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2135674ae819SStefano Zampini 
2136674ae819SStefano Zampini   /* Sum contributions from two levels */
2137dc359a40SStefano Zampini   if (applytranspose) {
2138dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2139dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2140dc359a40SStefano Zampini   } else {
2141674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
21428eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2143dc359a40SStefano Zampini   }
2144efc2fbd9SStefano Zampini   /* store p0 */
2145c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
2146efc2fbd9SStefano Zampini     PetscScalar *array;
2147efc2fbd9SStefano Zampini 
2148efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2149efc2fbd9SStefano Zampini     pcbddc->benign_p0 = array[pcbddc->local_primal_size-1];
2150efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2151efc2fbd9SStefano Zampini   }
2152674ae819SStefano Zampini   PetscFunctionReturn(0);
2153674ae819SStefano Zampini }
2154674ae819SStefano Zampini 
2155674ae819SStefano Zampini #undef __FUNCT__
2156674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
215712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2158674ae819SStefano Zampini {
2159674ae819SStefano Zampini   PetscErrorCode ierr;
2160674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
216158da7f69SStefano Zampini   PetscScalar    *array;
216212edc857SStefano Zampini   Vec            from,to;
2163674ae819SStefano Zampini 
2164674ae819SStefano Zampini   PetscFunctionBegin;
216512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
216612edc857SStefano Zampini     from = pcbddc->coarse_vec;
216712edc857SStefano Zampini     to = pcbddc->vec1_P;
216812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
216912edc857SStefano Zampini       Vec tvec;
217058da7f69SStefano Zampini 
217158da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
217258da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
217312edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
217458da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
217558da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
217658da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
217712edc857SStefano Zampini     }
217812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
217912edc857SStefano Zampini     from = pcbddc->vec1_P;
218012edc857SStefano Zampini     to = pcbddc->coarse_vec;
218112edc857SStefano Zampini   }
218212edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2183674ae819SStefano Zampini   PetscFunctionReturn(0);
2184674ae819SStefano Zampini }
2185674ae819SStefano Zampini 
2186674ae819SStefano Zampini #undef __FUNCT__
2187674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
218812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
2189674ae819SStefano Zampini {
2190674ae819SStefano Zampini   PetscErrorCode ierr;
2191674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
219258da7f69SStefano Zampini   PetscScalar    *array;
219312edc857SStefano Zampini   Vec            from,to;
2194674ae819SStefano Zampini 
2195674ae819SStefano Zampini   PetscFunctionBegin;
219612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
219712edc857SStefano Zampini     from = pcbddc->coarse_vec;
219812edc857SStefano Zampini     to = pcbddc->vec1_P;
219912edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
220012edc857SStefano Zampini     from = pcbddc->vec1_P;
220112edc857SStefano Zampini     to = pcbddc->coarse_vec;
220212edc857SStefano Zampini   }
220312edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
220412edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
220512edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
220612edc857SStefano Zampini       Vec tvec;
220758da7f69SStefano Zampini 
220812edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
220958da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
221058da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
221158da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
221258da7f69SStefano Zampini     }
221358da7f69SStefano Zampini   } else {
221458da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
221558da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
221612edc857SStefano Zampini     }
221712edc857SStefano Zampini   }
2218674ae819SStefano Zampini   PetscFunctionReturn(0);
2219674ae819SStefano Zampini }
2220674ae819SStefano Zampini 
2221984c4197SStefano Zampini /* uncomment for testing purposes */
2222984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
2223674ae819SStefano Zampini #undef __FUNCT__
2224674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
2225674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
2226674ae819SStefano Zampini {
2227674ae819SStefano Zampini   PetscErrorCode    ierr;
2228674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
2229674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
2230674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
2231984c4197SStefano Zampini   /* one and zero */
2232984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
2233984c4197SStefano Zampini   /* space to store constraints and their local indices */
22349162d606SStefano Zampini   PetscScalar       *constraints_data;
22359162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
22369162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
22379162d606SStefano Zampini   PetscInt          *constraints_n;
2238984c4197SStefano Zampini   /* iterators */
2239b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
2240984c4197SStefano Zampini   /* BLAS integers */
2241e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
2242e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2243c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2244727cdba6SStefano Zampini   /* reuse */
22450e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
22460e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2247984c4197SStefano Zampini   /* change of basis */
2248b3d85658SStefano Zampini   PetscBool         qr_needed;
22499162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
2250984c4197SStefano Zampini   /* auxiliary stuff */
225164efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
22528a0068c3SStefano Zampini   PetscInt          ncc;
2253984c4197SStefano Zampini   /* some quantities */
225445a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2255a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2256984c4197SStefano Zampini 
2257674ae819SStefano Zampini   PetscFunctionBegin;
22588e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
22598e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
22608e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2261088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
2262088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
22630e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
22640e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
22650e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
22660e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
22670e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2268088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2269cf5a6209SStefano Zampini 
2270cf5a6209SStefano Zampini   /* print some info */
2271cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
2272cf5a6209SStefano Zampini     IS       vertices;
2273cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
2274cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2275cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2276cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2277cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2278cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2279cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2280fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2281fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2282cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2283cf5a6209SStefano Zampini   }
2284cf5a6209SStefano Zampini 
2285cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
22869162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
2287cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
2288cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
2289cf5a6209SStefano Zampini     Vec          *localnearnullsp;
2290cf5a6209SStefano Zampini     PetscScalar  *array;
2291cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2292cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
2293674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
2294b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
2295674ae819SStefano Zampini     PetscScalar  *work;
2296674ae819SStefano Zampini     PetscReal    *singular_vals;
2297674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2298674ae819SStefano Zampini     PetscReal    *rwork;
2299674ae819SStefano Zampini #endif
2300674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2301674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
2302674ae819SStefano Zampini #else
2303964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
2304964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
2305674ae819SStefano Zampini #endif
2306674ae819SStefano Zampini 
2307674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
2308d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2309d06fc5fdSStefano Zampini     /* free unneeded index sets */
2310d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
2311d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2312674ae819SStefano Zampini     }
2313d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
2314d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
2315d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2316d06fc5fdSStefano Zampini       }
2317d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2318d06fc5fdSStefano Zampini       n_ISForEdges = 0;
2319d06fc5fdSStefano Zampini     }
2320d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
2321d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
2322d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2323d06fc5fdSStefano Zampini       }
2324d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2325d06fc5fdSStefano Zampini       n_ISForFaces = 0;
2326d06fc5fdSStefano Zampini     }
232770022509SStefano Zampini 
232870022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
232970022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
233070022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
233170022509SStefano Zampini     if (pcbddc->NullSpace) {
233270022509SStefano Zampini       PetscBool tbool[2],gbool[2];
233370022509SStefano Zampini 
233470022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2335b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
2336d06fc5fdSStefano Zampini         if (!ISForEdges) {
2337d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
2338d06fc5fdSStefano Zampini         }
2339b8ffe317SStefano Zampini       }
2340d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
2341d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
2342d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2343d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
2344d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
234598a51de6SStefano Zampini     }
234670022509SStefano Zampini #endif
234708122e43SStefano Zampini 
2348674ae819SStefano Zampini     /* check if near null space is attached to global mat */
2349674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2350674ae819SStefano Zampini     if (nearnullsp) {
2351674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2352f4ddd8eeSStefano Zampini       /* remove any stored info */
2353f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2354f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2355f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
2356f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2357f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
2358473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2359f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
2360f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2361f4ddd8eeSStefano Zampini       }
2362984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
2363984c4197SStefano Zampini       nnsp_size = 0;
2364674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
2365674ae819SStefano Zampini     }
2366984c4197SStefano Zampini     /* get max number of constraints on a single cc */
2367984c4197SStefano Zampini     max_constraints = nnsp_size;
2368984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
2369984c4197SStefano Zampini 
2370674ae819SStefano Zampini     /*
2371674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
23729162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
23739162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
23749162d606SStefano Zampini          There can be multiple constraints per connected component
2375674ae819SStefano Zampini                                                                                                                                                            */
2376674ae819SStefano Zampini     n_vertices = 0;
2377674ae819SStefano Zampini     if (ISForVertices) {
2378674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2379674ae819SStefano Zampini     }
23809162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
23819162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
23829162d606SStefano Zampini 
23839162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
23849162d606SStefano Zampini     total_counts *= max_constraints;
2385674ae819SStefano Zampini     total_counts += n_vertices;
23864641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
23879162d606SStefano Zampini 
2388674ae819SStefano Zampini     total_counts = 0;
2389674ae819SStefano Zampini     max_size_of_constraint = 0;
2390674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
23919162d606SStefano Zampini       IS used_is;
2392674ae819SStefano Zampini       if (i<n_ISForEdges) {
23939162d606SStefano Zampini         used_is = ISForEdges[i];
2394674ae819SStefano Zampini       } else {
23959162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
2396674ae819SStefano Zampini       }
23979162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2398674ae819SStefano Zampini       total_counts += j;
2399674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2400674ae819SStefano Zampini     }
24019162d606SStefano Zampini     ierr = PetscMalloc3(total_counts*max_constraints+n_vertices,&constraints_data,total_counts+n_vertices,&constraints_idxs,total_counts+n_vertices,&constraints_idxs_B);CHKERRQ(ierr);
24029162d606SStefano Zampini 
2403984c4197SStefano Zampini     /* get local part of global near null space vectors */
2404785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2405984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2406984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2407e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2408e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2409984c4197SStefano Zampini     }
2410674ae819SStefano Zampini 
2411242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
2412242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
2413a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2414242a89d7SStefano Zampini 
2415984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2416a773dcb8SStefano Zampini     if (!skip_lapack) {
2417674ae819SStefano Zampini       PetscScalar temp_work;
2418911cabfeSStefano Zampini 
2419674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2420984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2421785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2422785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2423785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2424674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2425785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2426674ae819SStefano Zampini #endif
2427674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2428c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2429c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2430674ae819SStefano Zampini       lwork = -1;
2431674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2432674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2433c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2434674ae819SStefano Zampini #else
2435c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2436674ae819SStefano Zampini #endif
2437674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2438984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2439674ae819SStefano Zampini #else /* on missing GESVD */
2440674ae819SStefano Zampini       /* SVD */
2441674ae819SStefano Zampini       PetscInt max_n,min_n;
2442674ae819SStefano Zampini       max_n = max_size_of_constraint;
2443984c4197SStefano Zampini       min_n = max_constraints;
2444984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
2445674ae819SStefano Zampini         min_n = max_size_of_constraint;
2446984c4197SStefano Zampini         max_n = max_constraints;
2447674ae819SStefano Zampini       }
2448785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2449674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2450785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2451674ae819SStefano Zampini #endif
2452674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2453674ae819SStefano Zampini       lwork = -1;
2454e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2455e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2456b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2457674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2458674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
24599162d606SStefano 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));
2460674ae819SStefano Zampini #else
24619162d606SStefano 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));
2462674ae819SStefano Zampini #endif
2463674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2464984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2465984c4197SStefano Zampini #endif /* on missing GESVD */
2466674ae819SStefano Zampini       /* Allocate optimal workspace */
2467674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2468854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2469674ae819SStefano Zampini     }
2470674ae819SStefano Zampini     /* Now we can loop on constraining sets */
2471674ae819SStefano Zampini     total_counts = 0;
24729162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
24739162d606SStefano Zampini     constraints_data_ptr[0] = 0;
2474674ae819SStefano Zampini     /* vertices */
24759162d606SStefano Zampini     if (n_vertices) {
2476674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
24779162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2478674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
24799162d606SStefano Zampini         constraints_n[total_counts] = 1;
24809162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
24819162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
24829162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2483674ae819SStefano Zampini         total_counts++;
2484674ae819SStefano Zampini       }
2485674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2486674ae819SStefano Zampini       n_vertices = total_counts;
2487674ae819SStefano Zampini     }
2488984c4197SStefano Zampini 
2489674ae819SStefano Zampini     /* edges and faces */
24909162d606SStefano Zampini     total_counts_cc = total_counts;
2491911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
24929162d606SStefano Zampini       IS        used_is;
24939162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
24949162d606SStefano Zampini 
2495911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
24969162d606SStefano Zampini         used_is = ISForEdges[ncc];
2497984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2498674ae819SStefano Zampini       } else {
24999162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
2500984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2501674ae819SStefano Zampini       }
2502674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
25039162d606SStefano Zampini 
25049162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
25059162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2506984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
2507984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2508674ae819SStefano Zampini       if (nnsp_has_cnst) {
25095b08dc53SStefano Zampini         PetscScalar quad_value;
25109162d606SStefano Zampini 
25119162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
25129162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
25139162d606SStefano Zampini 
2514a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
2515674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2516a773dcb8SStefano Zampini         } else {
2517a773dcb8SStefano Zampini           quad_value = 1.0;
2518a773dcb8SStefano Zampini         }
2519674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
25209162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
2521674ae819SStefano Zampini         }
25229162d606SStefano Zampini         temp_constraints++;
2523674ae819SStefano Zampini         total_counts++;
2524674ae819SStefano Zampini       }
2525674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
2526984c4197SStefano Zampini         PetscReal real_value;
25279162d606SStefano Zampini         PetscScalar *ptr_to_data;
25289162d606SStefano Zampini 
2529984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
25309162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
2531674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
25329162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
2533674ae819SStefano Zampini         }
2534984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2535984c4197SStefano Zampini         /* check if array is null on the connected component */
2536e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
25379162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
25385b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2539674ae819SStefano Zampini           temp_constraints++;
2540674ae819SStefano Zampini           total_counts++;
25419162d606SStefano Zampini           if (!idxs_copied) {
25429162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
25439162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
2544674ae819SStefano Zampini           }
2545674ae819SStefano Zampini         }
25469162d606SStefano Zampini       }
25479162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
254845a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2549eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2550a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
25519162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
25529162d606SStefano Zampini 
25539162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2554a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
25559162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
2556a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
25579162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
2558a773dcb8SStefano Zampini         } else { /* perform SVD */
2559984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
25609162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2561674ae819SStefano Zampini 
2562674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2563984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
2564984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
2565984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
2566984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
2567984c4197SStefano Zampini                 from that computed using LAPACKgesvd
2568984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
2569984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
2570984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
2571674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
2572e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2573984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2574674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
2575674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
25769162d606SStefano 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));
2577674ae819SStefano Zampini             }
2578674ae819SStefano Zampini           }
2579e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
2580e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2581e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
2582674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2583c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
2584674ae819SStefano Zampini #else
2585c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
2586674ae819SStefano Zampini #endif
2587674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2588984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
2589984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
2590674ae819SStefano Zampini           j = 0;
2591984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
2592674ae819SStefano Zampini           total_counts = total_counts-j;
259345a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
2594e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
2595c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2596c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2597c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
2598c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2599c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
2600c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2601674ae819SStefano Zampini           if (j<temp_constraints) {
2602984c4197SStefano Zampini             PetscInt ii;
2603984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
2604674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
26059162d606SStefano 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));
2606674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2607984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
2608674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
26099162d606SStefano 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];
2610674ae819SStefano Zampini               }
2611674ae819SStefano Zampini             }
2612674ae819SStefano Zampini           }
2613674ae819SStefano Zampini #else  /* on missing GESVD */
2614e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2615e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2616b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2617674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2618674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
26199162d606SStefano 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));
2620674ae819SStefano Zampini #else
26219162d606SStefano 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));
2622674ae819SStefano Zampini #endif
2623984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
2624674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2625984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
2626e310c8b4SStefano Zampini           k = temp_constraints;
2627e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
2628674ae819SStefano Zampini           j = 0;
2629e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
263045a1bb75SStefano Zampini           valid_constraints = k-j;
2631911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
2632984c4197SStefano Zampini #endif /* on missing GESVD */
2633674ae819SStefano Zampini         }
2634a773dcb8SStefano Zampini       }
26359162d606SStefano Zampini       /* update pointers information */
26369162d606SStefano Zampini       if (valid_constraints) {
26379162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
26389162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
26399162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
26409162d606SStefano Zampini         /* set change_of_basis flag */
264145a1bb75SStefano Zampini         if (boolforchange) {
2642b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
26439162d606SStefano Zampini         }
2644b3d85658SStefano Zampini         total_counts_cc++;
264545a1bb75SStefano Zampini       }
264645a1bb75SStefano Zampini     }
2647984c4197SStefano Zampini     /* free workspace */
26488f1c130eSStefano Zampini     if (!skip_lapack) {
2649984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
2650984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2651984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
2652984c4197SStefano Zampini #endif
2653984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
2654984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2655984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
2656984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2657984c4197SStefano Zampini #endif
2658984c4197SStefano Zampini     }
2659984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2660984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
2661984c4197SStefano Zampini     }
2662984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
2663cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
2664cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
2665cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2666cf5a6209SStefano Zampini     }
2667cf5a6209SStefano Zampini     if (n_ISForFaces) {
2668cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2669cf5a6209SStefano Zampini     }
2670cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
2671cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2672cf5a6209SStefano Zampini     }
2673cf5a6209SStefano Zampini     if (n_ISForEdges) {
2674cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2675cf5a6209SStefano Zampini     }
2676cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
267708122e43SStefano Zampini   } else {
267808122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2679984c4197SStefano Zampini 
268008122e43SStefano Zampini     total_counts = 0;
268108122e43SStefano Zampini     n_vertices = 0;
2682d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
2683d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
268408122e43SStefano Zampini     }
268508122e43SStefano Zampini     max_constraints = 0;
26869162d606SStefano Zampini     total_counts_cc = 0;
268708122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
268808122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
26899162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
269008122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
269108122e43SStefano Zampini     }
26929162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
26939162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
26949162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
26959162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
269674d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
26979162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
26989162d606SStefano Zampini     total_counts_cc = 0;
26999162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
27009162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
27019162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
270208122e43SStefano Zampini       }
270308122e43SStefano Zampini     }
27049162d606SStefano Zampini #if 0
27059162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
27069162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
27079162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
27089162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
27099162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
27109162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
27119162d606SStefano Zampini       }
27129162d606SStefano Zampini       printf("\n");
27139162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
27149162d606SStefano Zampini     }
27151b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
27168bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
27171b968477SStefano Zampini     }
27181b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
27198bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] sub %d, edge %d, n %d\n",PetscGlobalRank,i,(PetscBool)PetscBTLookup(sub_schurs->is_edge,i),pcbddc->adaptive_constraints_n[i+n_vertices]);
27201b968477SStefano Zampini     }
272108122e43SStefano Zampini #endif
272208122e43SStefano Zampini 
27238bec7fa6SStefano Zampini     max_size_of_constraint = 0;
27249162d606SStefano 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]);
27259162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
272608122e43SStefano Zampini     /* Change of basis */
2727b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
272808122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
272908122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
273008122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
2731b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
273208122e43SStefano Zampini         }
273308122e43SStefano Zampini       }
273408122e43SStefano Zampini     }
273508122e43SStefano Zampini   }
2736984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
2737019a44ceSStefano Zampini   /* allocating one extra space (in case an extra primal dof should be stored for the benign trick */
2738019a44ceSStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+1,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
273908122e43SStefano Zampini 
27409162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
27419162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
27429162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
27439162d606SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",constraints_idxs_ptr[total_counts_cc],i);
274408122e43SStefano Zampini   }
2745674ae819SStefano Zampini 
2746674ae819SStefano Zampini   /* Create constraint matrix */
2747674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
274816f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
2749984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
2750984c4197SStefano Zampini 
2751984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
2752a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
2753a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
275474d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
2755984c4197SStefano Zampini   total_primal_vertices=0;
2756b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
27579162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
27589162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2759984c4197SStefano Zampini     if (size_of_constraint == 1) {
27609162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
2761b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
276264efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
27639162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
27649162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
2765a717540cSStefano Zampini       }
2766b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
276774d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
2768a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
2769a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
2770a717540cSStefano Zampini       }
2771fa434743SStefano Zampini     } else {
2772b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
2773fa434743SStefano Zampini     }
2774a717540cSStefano Zampini   }
2775b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
2776b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
2777674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
277870022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2779b3d85658SStefano Zampini 
2780019a44ceSStefano Zampini   /* allocating one extra space (in case an extra primal dof should be stored for the benign trick */
2781019a44ceSStefano Zampini   ierr = PetscMalloc2(pcbddc->local_primal_size_cc+1,&pcbddc->local_primal_ref_node,pcbddc->local_primal_size_cc+1,&pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
27820e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
27830e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
2784984c4197SStefano Zampini 
2785984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
278674d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
2787785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2788984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
278974d5cdf7SStefano Zampini 
2790984c4197SStefano Zampini   j = total_primal_vertices;
279174d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
2792b3d85658SStefano Zampini   cum = total_primal_vertices;
27939162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
27944641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2795b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
2796b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
2797b3d85658SStefano Zampini       cum++;
27989162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
279974d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
280074d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
280174d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
280274d5cdf7SStefano Zampini       }
28039162d606SStefano Zampini       j += constraints_n[i];
2804674ae819SStefano Zampini     }
2805674ae819SStefano Zampini   }
2806674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2807674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2808088faed8SStefano Zampini 
2809674ae819SStefano Zampini   /* set values in constraint matrix */
2810984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
28110e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2812674ae819SStefano Zampini   }
2813984c4197SStefano Zampini   total_counts = total_primal_vertices;
28149162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
28154641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
28169162d606SStefano Zampini       PetscInt *cols;
28179162d606SStefano Zampini 
28189162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
28199162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
28209162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
28219162d606SStefano Zampini         PetscInt    row = total_counts+k;
28229162d606SStefano Zampini         PetscScalar *vals;
28239162d606SStefano Zampini 
28249162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
28259162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
28269162d606SStefano Zampini       }
28279162d606SStefano Zampini       total_counts += constraints_n[i];
2828674ae819SStefano Zampini     }
2829674ae819SStefano Zampini   }
2830674ae819SStefano Zampini   /* assembling */
2831674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2832674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2833088faed8SStefano Zampini 
2834984c4197SStefano Zampini   /*
283545a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2836984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2837984c4197SStefano Zampini   */
2838674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2839674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2840026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2841984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2842984c4197SStefano Zampini     /* working stuff for GEQRF */
284381d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2844984c4197SStefano Zampini     PetscBLASInt lqr_work;
2845984c4197SStefano Zampini     /* working stuff for UNGQR */
2846984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2847984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2848984c4197SStefano Zampini     /* working stuff for TRTRS */
2849984c4197SStefano Zampini     PetscScalar  *trs_rhs;
28503f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2851984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2852984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2853984c4197SStefano Zampini     PetscScalar  *start_vals;
2854984c4197SStefano Zampini     /* working stuff for values insertion */
28554641a718SStefano Zampini     PetscBT      is_primal;
285664efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
2857906d46d4SStefano Zampini     /* matrix sizes */
2858906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2859906d46d4SStefano Zampini     /* temporary change of basis */
2860906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2861cf5a6209SStefano Zampini     /* extra space for debugging */
2862cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
2863984c4197SStefano Zampini 
2864906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2865906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
286616f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2867bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
2868906d46d4SStefano Zampini     /* nonzeros for local mat */
2869bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
2870bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
28719162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
2872a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
28739162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2874a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
28759162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
2876a717540cSStefano Zampini         } else {
28779162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
28789162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
2879a717540cSStefano Zampini         }
2880a717540cSStefano Zampini       }
2881a717540cSStefano Zampini     }
2882906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2883bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2884a717540cSStefano Zampini     /* Set initial identity in the matrix */
2885bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
2886906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2887a717540cSStefano Zampini     }
2888a717540cSStefano Zampini 
2889a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2890a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2891a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2892a717540cSStefano Zampini     }
2893a717540cSStefano Zampini 
2894a717540cSStefano Zampini 
2895a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2896a717540cSStefano Zampini     /*
2897a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2898a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2899a717540cSStefano Zampini 
2900a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2901a717540cSStefano Zampini 
2902a6b551f4SStefano 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)
2903a6b551f4SStefano Zampini 
2904a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2905a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2906a717540cSStefano Zampini             |              ...                        |
2907a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2908a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2909a717540cSStefano Zampini 
2910a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2911a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2912a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2913a6b551f4SStefano Zampini 
2914a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2915a717540cSStefano Zampini     */
2916a717540cSStefano Zampini     if (qr_needed) {
2917984c4197SStefano Zampini       /* space to store Q */
2918854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2919984c4197SStefano Zampini       /* first we issue queries for optimal work */
29203f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
29213f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
29223f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2923984c4197SStefano Zampini       lqr_work = -1;
29243f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2925984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
2926984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
2927785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
2928984c4197SStefano Zampini       lgqr_work = -1;
29293f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
29303f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
29313f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
29323f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
29333f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
29343f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
2935984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
2936984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
2937785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
2938984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
2939785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
2940984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
2941785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
2942a717540cSStefano Zampini       /* allocating workspace for check */
2943a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
2944cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
2945a717540cSStefano Zampini       }
2946a717540cSStefano Zampini     }
2947984c4197SStefano Zampini     /* array to store whether a node is primal or not */
29484641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
2949473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
29500e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
295139e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
295239e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
29534641a718SStefano Zampini     }
295439e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
295539e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
295639e2fb2aSStefano Zampini     }
295739e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
2958984c4197SStefano Zampini 
2959a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
29609162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
29619162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
29624641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
2963984c4197SStefano Zampini         /* get constraint info */
29649162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
2965984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
2966984c4197SStefano Zampini 
2967984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
29689162d606SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraints %d: %d need a change of basis (size %d)\n",total_counts,primal_dofs,size_of_constraint);CHKERRQ(ierr);
2969674ae819SStefano Zampini         }
2970984c4197SStefano Zampini 
2971fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
2972a717540cSStefano Zampini 
2973a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
2974a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
29759162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2976a717540cSStefano Zampini           }
2977984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
29789162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2979984c4197SStefano Zampini 
2980984c4197SStefano Zampini           /* compute QR decomposition of constraints */
29813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
29823f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
29833f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2984674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
29853f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
2986984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
2987674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2988984c4197SStefano Zampini 
2989984c4197SStefano Zampini           /* explictly compute R^-T */
2990984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
2991984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
29923f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
29933f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
29943f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
29953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
2996984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
29973f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
2998984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
2999984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3000984c4197SStefano Zampini 
3001a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
30023f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
30033f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
30043f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
30053f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3006984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30073f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3008984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3009984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3010984c4197SStefano Zampini 
3011984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3012984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3013984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
30143f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
30153f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
30163f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
30173f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
30183f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
30193f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3020984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30219162d606SStefano 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));
3022984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
30239162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3024984c4197SStefano Zampini 
3025984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
30269162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3027984c4197SStefano Zampini           /* insert cols for primal dofs */
3028984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3029984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
30309162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3031906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3032984c4197SStefano Zampini           }
3033984c4197SStefano Zampini           /* insert cols for dual dofs */
3034984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
30359162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3036984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
30379162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3038906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3039984c4197SStefano Zampini               j++;
3040674ae819SStefano Zampini             }
3041674ae819SStefano Zampini           }
3042984c4197SStefano Zampini 
3043984c4197SStefano Zampini           /* check change of basis */
3044984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3045984c4197SStefano Zampini             PetscInt   ii,jj;
3046984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3047c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3048c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3049c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3050c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3051c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3052c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3053984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3054cf5a6209SStefano 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));
3055984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3056984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3057984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3058cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3059cf5a6209SStefano Zampini                 if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
3060674ae819SStefano Zampini               }
3061674ae819SStefano Zampini             }
3062984c4197SStefano Zampini             if (!valid_qr) {
306322d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3064984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3065984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3066cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3067cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not orthogonal to constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
3068674ae819SStefano Zampini                   }
3069cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3070cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not unitary w.r.t constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
3071984c4197SStefano Zampini                   }
3072984c4197SStefano Zampini                 }
3073984c4197SStefano Zampini               }
3074674ae819SStefano Zampini             } else {
307522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3076674ae819SStefano Zampini             }
3077674ae819SStefano Zampini           }
3078a717540cSStefano Zampini         } else { /* simple transformation block */
3079a717540cSStefano Zampini           PetscInt    row,col;
3080a6b551f4SStefano Zampini           PetscScalar val,norm;
3081a6b551f4SStefano Zampini 
3082a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
30839162d606SStefano 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));
3084a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
30859162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
30869162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3087bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
30889162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3089906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
30909162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3091a717540cSStefano Zampini             } else {
3092a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
30939162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3094a717540cSStefano Zampini                 if (row != col) {
30959162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3096a717540cSStefano Zampini                 } else {
30979162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3098a717540cSStefano Zampini                 }
3099906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3100a717540cSStefano Zampini               }
3101a717540cSStefano Zampini             }
3102a717540cSStefano Zampini           }
310398a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
310422d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3105a717540cSStefano Zampini           }
3106674ae819SStefano Zampini         }
3107984c4197SStefano Zampini       } else {
3108984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
31099162d606SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %d does not need a change of basis (size %d)\n",total_counts,size_of_constraint);CHKERRQ(ierr);
3110674ae819SStefano Zampini         }
3111674ae819SStefano Zampini       }
3112674ae819SStefano Zampini     }
3113a717540cSStefano Zampini 
3114a717540cSStefano Zampini     /* free workspace */
3115a717540cSStefano Zampini     if (qr_needed) {
3116984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
3117cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3118984c4197SStefano Zampini       }
3119984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3120984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3121984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3122984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3123984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3124674ae819SStefano Zampini     }
3125a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3126906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3127906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3128906d46d4SStefano Zampini 
3129906d46d4SStefano Zampini     /* assembling of global change of variable */
3130bbb9e6c6SStefano Zampini     {
3131bbb9e6c6SStefano Zampini       Mat      tmat;
313216f15bc4SStefano Zampini       PetscInt bs;
313316f15bc4SStefano Zampini 
3134906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3135906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3136bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3137bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3138bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3139bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
314016f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
314116f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3142906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3143bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3144bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3145bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3146bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3147bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3148e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3149e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3150bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3151bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3152906d46d4SStefano Zampini     }
3153906d46d4SStefano Zampini     /* check */
3154906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
3155906d46d4SStefano Zampini       PetscReal error;
3156906d46d4SStefano Zampini       Vec       x,x_change;
3157906d46d4SStefano Zampini 
3158906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3159906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3160906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3161906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3162e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3163e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3164bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
3165e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3166e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3167906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
3168906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3169906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3170906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3171bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
3172906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
3173906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3174906d46d4SStefano Zampini     }
3175b96c3477SStefano Zampini 
3176b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
3177b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
3178b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
3179b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
3180ac632422SStefano Zampini         Mat                    S_new,tmat;
3181b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
3182b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
3183b087196eSStefano Zampini         const PetscScalar      *array;
3184b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
3185b087196eSStefano Zampini         PetscInt               i,n_V;
3186bbb9e6c6SStefano Zampini 
3187bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
31886816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
3189b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
3190b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
3191b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
3192b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
3193bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
3194b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
3195ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3196b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
3197ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3198b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3199b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
3200b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3201b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3202b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
3203b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
3204b087196eSStefano Zampini           PetscScalar val;
3205b087196eSStefano Zampini           PetscInt    idx;
3206b087196eSStefano Zampini 
3207b087196eSStefano Zampini           idx = idxs_V[i];
3208b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
3209b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
3210b087196eSStefano Zampini         }
3211b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3212b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3213ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
3214ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3215ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
3216ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3217b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
3218ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3219b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3220ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
3221ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3222ac632422SStefano Zampini         }
3223b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
3224b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3225b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3226b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3227b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
3228b96c3477SStefano Zampini       }
3229b96c3477SStefano Zampini     }
3230906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
3231906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
3232b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3233b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
3234b9b85e73SStefano Zampini   }
3235906d46d4SStefano Zampini 
3236906d46d4SStefano Zampini   /* set up change of basis context */
3237906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
3238906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
3239906d46d4SStefano Zampini 
3240906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
3241906d46d4SStefano Zampini       PetscInt global_size,local_size;
3242906d46d4SStefano Zampini 
3243906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3244906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3245906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
3246906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3247906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
3248906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
3249906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3250906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3251906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3252906d46d4SStefano Zampini     } else {
3253906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3254906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3255906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3256906d46d4SStefano Zampini     }
3257906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
3258906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3259906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3260906d46d4SStefano Zampini     } else {
3261906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3262906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3263906d46d4SStefano Zampini     }
3264906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3265906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3266906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3267906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3268b9b85e73SStefano Zampini   }
3269a717540cSStefano Zampini 
3270019a44ceSStefano Zampini   /* add pressure dof to set of primal nodes for numbering purposes */
3271c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
3272c9ed8603SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx;
3273d16cbb6bSStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx;
3274019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
3275019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
3276019a44ceSStefano Zampini     pcbddc->local_primal_size++;
3277019a44ceSStefano Zampini   }
3278019a44ceSStefano Zampini 
3279019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
3280727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
3281727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
3282aff50787SStefano Zampini     ierr = PetscMemcmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc*sizeof(PetscScalar),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
3283c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
32840e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
3285aff50787SStefano Zampini       ierr = PetscMemcmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscScalar),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
3286727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3287727cdba6SStefano Zampini     }
32880e6343abSStefano Zampini   }
32890e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3290727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3291727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3292727cdba6SStefano Zampini 
3293a717540cSStefano Zampini   /* flush dbg viewer */
3294b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
3295b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3296b8ffe317SStefano Zampini   }
3297a717540cSStefano Zampini 
3298e310c8b4SStefano Zampini   /* free workspace */
3299a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
33004641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
330108122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
33029162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
33039162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
330408122e43SStefano Zampini   } else {
33059162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
33069162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
33079162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
330808122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
330908122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
33109162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
33119162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
331208122e43SStefano Zampini   }
3313674ae819SStefano Zampini   PetscFunctionReturn(0);
3314674ae819SStefano Zampini }
3315674ae819SStefano Zampini 
3316674ae819SStefano Zampini #undef __FUNCT__
3317674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
3318674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3319674ae819SStefano Zampini {
3320674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3321674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
3322674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
33237fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
3324674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
3325674ae819SStefano Zampini 
3326674ae819SStefano Zampini   PetscFunctionBegin;
33278e61c736SStefano Zampini   /* Reset previously computed graph */
33288e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3329674ae819SStefano Zampini   /* Init local Graph struct */
33307fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
33313bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3332674ae819SStefano Zampini 
3333575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
3334575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
3335575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
3336575ad6abSStefano Zampini   }
33379577ea80SStefano Zampini 
3338674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
33394d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
33404d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
33414d379d7bSStefano Zampini     PetscInt  nvtxs;
3342e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
3343674ae819SStefano Zampini 
33444d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
33452fffb893SStefano Zampini 
33462fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
33472fffb893SStefano Zampini       if (flg_row) {
33484d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3349b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
33502fffb893SStefano Zampini       }
33512fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
33529b28b941SStefano Zampini     } else if (pcbddc->current_level && pcis->n_B) { /* just compute subdomain's connected components for coarser levels when the local boundary is not empty */
33534d379d7bSStefano Zampini       IS                     is_dummy;
33544d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
33554d379d7bSStefano Zampini       PetscInt               j,sum;
33564d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
33574d379d7bSStefano Zampini       const PetscInt         *idxs;
33584d379d7bSStefano Zampini       PCBDDCGraph            graph;
33594d379d7bSStefano Zampini       PetscBT                is_on_boundary;
33604d379d7bSStefano Zampini 
33614d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
33624d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
33634d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
33644d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
33657fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
33664d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3367e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3368e496cd5dSStefano Zampini       if (flg_row) {
33694d379d7bSStefano Zampini         graph->xadj = xadj;
33704d379d7bSStefano Zampini         graph->adjncy = adjncy;
3371e496cd5dSStefano Zampini       }
33724d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
33734d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3374e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
33754d379d7bSStefano Zampini 
33764d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
33779b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
33784d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
33794d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
33804d379d7bSStefano Zampini         }
33814d379d7bSStefano Zampini       }
33824d379d7bSStefano Zampini 
3383e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
33844d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
33854d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
33864d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
33874d379d7bSStefano Zampini       }
33884d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
33894d379d7bSStefano Zampini 
3390e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
33914d379d7bSStefano Zampini       sum = 0;
33924d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
33934d379d7bSStefano Zampini         PetscInt sizecc = 0;
33944d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
33954d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
33964d379d7bSStefano Zampini             sizecc++;
33974d379d7bSStefano Zampini           }
33984d379d7bSStefano Zampini         }
33994d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
34004d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
34014d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
34024d379d7bSStefano Zampini           }
34034d379d7bSStefano Zampini         }
34044d379d7bSStefano Zampini         sum += sizecc*sizecc;
34054d379d7bSStefano Zampini       }
34064d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
34074d379d7bSStefano Zampini       sum = 0;
3408e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
34094d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
34104d379d7bSStefano Zampini         cxadj[i] = sum;
34114d379d7bSStefano Zampini         sum += temp;
34124d379d7bSStefano Zampini       }
3413e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
34144d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
34154d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
34164d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
34174d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
34184d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
34194d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
34204d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
34214d379d7bSStefano Zampini                 sizecc++;
34224d379d7bSStefano Zampini               }
34234d379d7bSStefano Zampini             }
34244d379d7bSStefano Zampini           }
34254d379d7bSStefano Zampini         }
34264d379d7bSStefano Zampini       }
34279b28b941SStefano Zampini       if (sum) {
3428e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
34294d379d7bSStefano Zampini       } else {
34304d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
34314d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
34324d379d7bSStefano Zampini       }
34334d379d7bSStefano Zampini       graph->xadj = 0;
34344d379d7bSStefano Zampini       graph->adjncy = 0;
34354d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
34364d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
34374d379d7bSStefano Zampini     }
3438674ae819SStefano Zampini   }
34399b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
34409b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3441674ae819SStefano Zampini   }
3442674ae819SStefano Zampini 
344363602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3444674ae819SStefano Zampini   vertex_size = 1;
344563602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
344663602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
344795ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
344863602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3449e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
345063602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3451674ae819SStefano Zampini       }
345263602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
345363602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
345463602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3455674ae819SStefano Zampini     }
345663602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3457674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
345863602bcaSStefano Zampini   } else {
345963602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
346063602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3461854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
346263602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
346363602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
346463602bcaSStefano Zampini       }
346563602bcaSStefano Zampini     }
3466674ae819SStefano Zampini   }
3467674ae819SStefano Zampini 
3468674ae819SStefano Zampini   /* Setup of Graph */
3469785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3470e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3471785d1243SStefano Zampini   }
3472785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3473e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3474785d1243SStefano Zampini   }
3475302440fdSBarry Smith   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);CHKERRQ(ierr);
3476674ae819SStefano Zampini 
3477674ae819SStefano Zampini   /* Graph's connected components analysis */
3478674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3479674ae819SStefano Zampini 
3480674ae819SStefano Zampini   /* print some info to stdout */
3481674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3482302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3483674ae819SStefano Zampini   }
3484fb180af4SStefano Zampini 
3485fb180af4SStefano Zampini   /* mark topography has done */
3486fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3487674ae819SStefano Zampini   PetscFunctionReturn(0);
3488674ae819SStefano Zampini }
3489674ae819SStefano Zampini 
3490dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3491674ae819SStefano Zampini #undef __FUNCT__
3492674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3493dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3494674ae819SStefano Zampini {
3495dc456d91SStefano Zampini   PetscSF        sf;
3496dc456d91SStefano Zampini   PetscLayout    map;
3497dc456d91SStefano Zampini   const PetscInt *idxs;
3498dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
3499dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
3500dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
3501dc456d91SStefano Zampini   PetscMPIInt    commsize;
3502674ae819SStefano Zampini   PetscBool      first_found;
3503674ae819SStefano Zampini   PetscErrorCode ierr;
3504674ae819SStefano Zampini 
3505674ae819SStefano Zampini   PetscFunctionBegin;
3506dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
3507dc456d91SStefano Zampini   if (subset_mult) {
3508dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
3509dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
3510dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
3511674ae819SStefano Zampini   }
3512dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
3513dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
3514dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
3515dc456d91SStefano Zampini   for (i=0;i<n;i++) {
3516dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
3517dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
3518674ae819SStefano Zampini   }
3519dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
3520dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3521dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
3522dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
3523dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
3524dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
3525dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
3526dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
3527dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
3528dc456d91SStefano Zampini 
3529dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
3530dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
3531dc456d91SStefano Zampini   if (subset_mult) {
3532dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3533dc456d91SStefano Zampini 
3534dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3535dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
3536dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3537674ae819SStefano Zampini   } else {
3538dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
3539674ae819SStefano Zampini   }
3540dc456d91SStefano Zampini   /* local size of new subset */
3541dc456d91SStefano Zampini   n_n = 0;
3542dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
3543dc456d91SStefano Zampini 
3544dc456d91SStefano Zampini   /* global indexes in layout */
3545dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
3546dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
3547dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
3548dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
3549dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
3550dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
3551dc456d91SStefano Zampini 
3552dc456d91SStefano Zampini   /* reduce from leaves to roots */
3553dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
355464a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
355564a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
3556dc456d91SStefano Zampini 
3557dc456d91SStefano Zampini   /* count indexes in local part of layout */
3558674ae819SStefano Zampini   nlocals = 0;
3559674ae819SStefano Zampini   first_index = -1;
3560674ae819SStefano Zampini   first_found = PETSC_FALSE;
3561dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
3562dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
3563674ae819SStefano Zampini       first_found = PETSC_TRUE;
3564674ae819SStefano Zampini       first_index = i;
3565674ae819SStefano Zampini     }
3566dc456d91SStefano Zampini     nlocals += root_data[i];
3567674ae819SStefano Zampini   }
3568dc456d91SStefano Zampini 
3569dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
35705fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
3571dc456d91SStefano Zampini   start = 0;
357264a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
35735fa240b1SStefano Zampini #else
357464a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
35755fa240b1SStefano Zampini   start = start-nlocals;
35765fa240b1SStefano Zampini #endif
35775fa240b1SStefano Zampini 
3578dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
3579dc456d91SStefano Zampini     *N_n = start + nlocals;
3580dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
3581dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3582674ae819SStefano Zampini   }
35835fa240b1SStefano Zampini 
35845fa240b1SStefano Zampini   /* adapt root data with cumulative */
3585674ae819SStefano Zampini   if (first_found) {
3586dc456d91SStefano Zampini     PetscInt old_index;
3587dc456d91SStefano Zampini 
3588dc456d91SStefano Zampini     root_data[first_index] += start;
3589674ae819SStefano Zampini     old_index = first_index;
3590dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
3591dc456d91SStefano Zampini       if (root_data[i]) {
3592dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
3593674ae819SStefano Zampini         old_index = i;
3594674ae819SStefano Zampini       }
3595674ae819SStefano Zampini     }
3596674ae819SStefano Zampini   }
3597dc456d91SStefano Zampini 
3598dc456d91SStefano Zampini   /* from roots to leaves */
3599dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3600dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3601dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
3602dc456d91SStefano Zampini 
3603dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
3604dc456d91SStefano Zampini   if (subset_mult) {
3605dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3606dc456d91SStefano Zampini     PetscInt        cum;
3607dc456d91SStefano Zampini 
3608dc456d91SStefano Zampini     cum = 0;
3609dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3610dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3611dc456d91SStefano Zampini       PetscInt j;
3612dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
3613674ae819SStefano Zampini     }
3614dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3615674ae819SStefano Zampini   } else {
3616dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3617dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
3618674ae819SStefano Zampini     }
3619674ae819SStefano Zampini   }
3620dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
3621dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
3622674ae819SStefano Zampini   PetscFunctionReturn(0);
3623674ae819SStefano Zampini }
36249a7d3425SStefano Zampini 
36259a7d3425SStefano Zampini #undef __FUNCT__
36269a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
36279a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
36289a7d3425SStefano Zampini {
36299a7d3425SStefano Zampini   PetscInt       i,j;
36309a7d3425SStefano Zampini   PetscScalar    *alphas;
36319a7d3425SStefano Zampini   PetscErrorCode ierr;
36329a7d3425SStefano Zampini 
36339a7d3425SStefano Zampini   PetscFunctionBegin;
36349a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
3635785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
36369a7d3425SStefano Zampini   for (i=0;i<n;i++) {
36379a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
36389a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
36399a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
36409a7d3425SStefano Zampini   }
36419a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
36429a7d3425SStefano Zampini   PetscFunctionReturn(0);
36439a7d3425SStefano Zampini }
36449a7d3425SStefano Zampini 
3645e7931f94SStefano Zampini #undef __FUNCT__
364670cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
3647b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
3648e7931f94SStefano Zampini {
364952e5ac9dSStefano Zampini   IS             ranks_send_to;
3650e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
3651e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
365252e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
365352e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
36543837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
36552b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
3656e7931f94SStefano Zampini   PetscSubcomm   subcomm;
365752e5ac9dSStefano Zampini   PetscErrorCode ierr;
3658a57a6d2fSStefano Zampini 
3659e7931f94SStefano Zampini   PetscFunctionBegin;
36602b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
36612b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
36622b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
3663e7931f94SStefano Zampini 
3664e7931f94SStefano Zampini   /* Get info on mapping */
36653bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
36663bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3667e7931f94SStefano Zampini 
3668e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
3669785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
3670e7931f94SStefano Zampini   xadj[0] = 0;
3671e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
3672785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
3673785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
3674e7931f94SStefano Zampini 
36752b510759SStefano Zampini   if (threshold) {
3676d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
36772b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3678d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3679d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3680d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3681d023bfaeSStefano Zampini         xadj_count++;
3682e7931f94SStefano Zampini       }
3683e7931f94SStefano Zampini     }
3684d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3685c8587f34SStefano Zampini   } else {
3686e7931f94SStefano Zampini     if (xadj[1]) {
3687e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3688e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3689c8587f34SStefano Zampini     }
3690e7931f94SStefano Zampini   }
36913bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3692e7931f94SStefano Zampini   if (use_square) {
3693e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3694e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3695e7931f94SStefano Zampini     }
3696e7931f94SStefano Zampini   }
3697e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3698e7931f94SStefano Zampini 
36993837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3700e7931f94SStefano Zampini 
3701e7931f94SStefano Zampini   /*
3702e7931f94SStefano Zampini     Restrict work on active processes only.
3703e7931f94SStefano Zampini   */
3704e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3705e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3706e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
37072b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3708d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3709e7931f94SStefano Zampini   if (color) {
3710e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3711e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3712e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3713c8587f34SStefano Zampini   } else {
371452e5ac9dSStefano Zampini     Mat             subdomain_adj;
371552e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
371652e5ac9dSStefano Zampini     MatPartitioning partitioner;
371752e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
371852e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
3719b0c7d250SStefano Zampini     PetscBool       aggregate;
3720b0c7d250SStefano Zampini 
3721306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
3722785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3723e7931f94SStefano Zampini     prank = rank;
3724306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
37258002ef2cSStefano Zampini     /*
3726e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3727e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3728c8587f34SStefano Zampini     }
37298002ef2cSStefano Zampini     */
3730e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3731e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3732c8587f34SStefano Zampini     }
3733e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3734b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
3735b0c7d250SStefano Zampini     if (aggregate) {
3736b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
3737b0c7d250SStefano Zampini       PetscMPIInt nrank;
3738b0c7d250SStefano Zampini       PetscScalar *vals;
3739b0c7d250SStefano Zampini 
3740b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
3741b0c7d250SStefano Zampini       lrows = 0;
3742b0c7d250SStefano Zampini       if (nrank<redprocs) {
3743b0c7d250SStefano Zampini         lrows = size/redprocs;
3744b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
3745b0c7d250SStefano Zampini       }
37465fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
3747b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
3748b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3749b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3750b0c7d250SStefano Zampini       row = nrank;
3751b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
3752b0c7d250SStefano Zampini       cols = adjncy;
3753b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
3754b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
3755b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
3756b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3757b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
375852e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
375952e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
376052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3761b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
3762b0c7d250SStefano Zampini     } else {
3763306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
3764b0c7d250SStefano Zampini     }
376522b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3766e7931f94SStefano Zampini 
3767e7931f94SStefano Zampini     /* Partition */
3768306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
3769e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3770e7931f94SStefano Zampini     if (use_vwgt) {
37713837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3772e7931f94SStefano Zampini       v_wgt[0] = local_size;
3773e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3774c8587f34SStefano Zampini     }
377528143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
377628143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3777e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3778e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
377922b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3780e7931f94SStefano Zampini 
378152e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
378252e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
378352e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
378452e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3785b0c7d250SStefano Zampini     if (!redprocs) {
3786b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
378728143c3dSStefano Zampini     } else {
3788b0c7d250SStefano Zampini       PetscInt    idxs[1];
3789b0c7d250SStefano Zampini       PetscMPIInt tag;
3790b0c7d250SStefano Zampini       MPI_Request *reqs;
3791b0c7d250SStefano Zampini 
3792b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
3793b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
3794b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
3795b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
379628143c3dSStefano Zampini       }
3797b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
3798b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3799b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
3800b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
3801e7931f94SStefano Zampini     }
380252e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3803e7931f94SStefano Zampini     /* clean up */
3804e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
380552e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
3806e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3807e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3808e7931f94SStefano Zampini   }
3809e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3810e7931f94SStefano Zampini 
3811e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3812e7931f94SStefano Zampini   i = 1;
3813e7931f94SStefano Zampini   if (color) i=0;
3814e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3815e7931f94SStefano Zampini   /* get back IS */
3816e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3817e7931f94SStefano Zampini   PetscFunctionReturn(0);
3818e7931f94SStefano Zampini }
3819e7931f94SStefano Zampini 
3820e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3821e7931f94SStefano Zampini 
3822e7931f94SStefano Zampini #undef __FUNCT__
3823e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
382453a05cb3SStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, PetscBool restrict_full, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
3825e7931f94SStefano Zampini {
382670cf5478SStefano Zampini   Mat                    local_mat;
3827e7931f94SStefano Zampini   IS                     is_sends_internal;
38289d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
382928143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
38309d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3831e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3832e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3833e7931f94SStefano Zampini   const PetscInt*        is_indices;
3834e7931f94SStefano Zampini   MatType                new_local_type;
3835e7931f94SStefano Zampini   /* buffers */
3836e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
383728143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
38389d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3839e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3840e7931f94SStefano Zampini   /* MPI */
384128143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
384228143c3dSStefano Zampini   PetscSubcomm           subcomm;
3843e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
384428143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
384528143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
384628143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
384728143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
384828143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3849e7931f94SStefano Zampini   PetscErrorCode         ierr;
3850e7931f94SStefano Zampini 
3851e7931f94SStefano Zampini   PetscFunctionBegin;
385228143c3dSStefano Zampini   /* TODO: add missing checks */
385328143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
385428143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
385528143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
385628143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3857e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
385828143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3859e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3860e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3861e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3862e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3863e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
386428143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
386570cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
386670cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
386728143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
386870cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
386970cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
387070cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
387170cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
387270cf5478SStefano Zampini   }
3873e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3874e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3875e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3876e7931f94SStefano Zampini   if (!is_sends) {
387728143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
3878b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
3879c8587f34SStefano Zampini   } else {
3880e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3881e7931f94SStefano Zampini     is_sends_internal = is_sends;
3882c8587f34SStefano Zampini   }
3883e7931f94SStefano Zampini 
3884e7931f94SStefano Zampini   /* get comm */
3885a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3886e7931f94SStefano Zampini 
3887e7931f94SStefano Zampini   /* compute number of sends */
3888e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3889e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3890e7931f94SStefano Zampini 
3891e7931f94SStefano Zampini   /* compute number of receives */
3892e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3893785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3894e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3895e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3896e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3897e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3898e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3899e7931f94SStefano Zampini 
390028143c3dSStefano Zampini   /* restrict comm if requested */
390128143c3dSStefano Zampini   subcomm = 0;
390228143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
390328143c3dSStefano Zampini   if (restrict_comm) {
3904779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
3905779c1cceSStefano Zampini 
390628143c3dSStefano Zampini     color = 0;
390753a05cb3SStefano Zampini     if (restrict_full) {
390853a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
390953a05cb3SStefano Zampini     } else {
391053a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
391153a05cb3SStefano Zampini     }
391228143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
391328143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
391428143c3dSStefano Zampini     /* check if reuse has been requested */
391528143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
391628143c3dSStefano Zampini       if (*mat_n) {
391728143c3dSStefano Zampini         PetscMPIInt subcommsize2;
391828143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
391928143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
392028143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
392128143c3dSStefano Zampini       } else {
392228143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
392328143c3dSStefano Zampini       }
392428143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
3925779c1cceSStefano Zampini       PetscMPIInt rank;
3926779c1cceSStefano Zampini 
3927779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
392828143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
392928143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
393028143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3931306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
393228143c3dSStefano Zampini     }
393328143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
393428143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
393528143c3dSStefano Zampini   } else {
393628143c3dSStefano Zampini     comm_n = comm;
393728143c3dSStefano Zampini   }
393828143c3dSStefano Zampini 
3939e7931f94SStefano Zampini   /* prepare send/receive buffers */
3940785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
3941e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
3942785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
3943e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
394428143c3dSStefano Zampini   if (nis) {
3945854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
394628143c3dSStefano Zampini   }
3947e7931f94SStefano Zampini 
394828143c3dSStefano Zampini   /* Get data from local matrices */
3949e7931f94SStefano Zampini   if (!isdense) {
3950a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
3951e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
3952e7931f94SStefano Zampini     /*
3953e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
3954e7931f94SStefano Zampini        send_buffer_idxs should contain:
3955e7931f94SStefano Zampini        - MatType_PRIVATE type
3956e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
3957e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
3958e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
3959e7931f94SStefano Zampini     */
3960e7931f94SStefano Zampini   } else {
3961e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
39623bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
3963854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
3964e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
3965e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
39663bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3967e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
39683bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3969e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
3970e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
3971e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
3972e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
3973c8587f34SStefano Zampini     }
3974c8587f34SStefano Zampini   }
3975e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
397628143c3dSStefano Zampini   /* additional is (if any) */
397728143c3dSStefano Zampini   if (nis) {
397828143c3dSStefano Zampini     PetscMPIInt psum;
397928143c3dSStefano Zampini     PetscInt j;
398028143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
398128143c3dSStefano Zampini       PetscInt plen;
398228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
398328143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
398428143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
398528143c3dSStefano Zampini     }
3986854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
398728143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
398828143c3dSStefano Zampini       PetscInt plen;
398928143c3dSStefano Zampini       const PetscInt *is_array_idxs;
399028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
399128143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
399228143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
399328143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
399428143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
399528143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
399628143c3dSStefano Zampini     }
399728143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
399828143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
399928143c3dSStefano Zampini     }
400028143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
400128143c3dSStefano Zampini   }
400228143c3dSStefano Zampini 
4003e7931f94SStefano Zampini   buf_size_idxs = 0;
4004e7931f94SStefano Zampini   buf_size_vals = 0;
400528143c3dSStefano Zampini   buf_size_idxs_is = 0;
4006e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4007e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4008e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
400928143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4010e7931f94SStefano Zampini   }
4011785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4012785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
401395ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4014e7931f94SStefano Zampini 
4015e7931f94SStefano Zampini   /* get new tags for clean communications */
4016e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4017e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
401828143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4019e7931f94SStefano Zampini 
4020e7931f94SStefano Zampini   /* allocate for requests */
4021785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4022785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
402395ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4024785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4025785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
402695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4027e7931f94SStefano Zampini 
4028e7931f94SStefano Zampini   /* communications */
4029e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4030e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
403128143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4032e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4033e7931f94SStefano Zampini     source_dest = onodes[i];
4034e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4035e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4036e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4037e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
403828143c3dSStefano Zampini     if (nis) {
403928143c3dSStefano Zampini       ierr = MPI_Irecv(ptr_idxs_is,olengths_idxs_is[i],MPIU_INT,source_dest,tag_idxs_is,comm,&recv_req_idxs_is[i]);CHKERRQ(ierr);
404028143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
404128143c3dSStefano Zampini     }
4042e7931f94SStefano Zampini   }
4043e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4044e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4045e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4046e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
404728143c3dSStefano Zampini     if (nis) {
404828143c3dSStefano Zampini       ierr = MPI_Isend(send_buffer_idxs_is,ilengths_idxs_is[source_dest],MPIU_INT,source_dest,tag_idxs_is,comm,&send_req_idxs_is[i]);CHKERRQ(ierr);
404928143c3dSStefano Zampini     }
4050e7931f94SStefano Zampini   }
4051e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4052e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4053e7931f94SStefano Zampini 
4054e7931f94SStefano Zampini   /* assemble new l2g map */
4055e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4056e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
40579d30be91SStefano Zampini   new_local_rows = 0;
4058e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
40599d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4060e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4061e7931f94SStefano Zampini   }
40629d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4063e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
40649d30be91SStefano Zampini   new_local_rows = 0;
4065e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
40669d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
40679d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4068e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4069e7931f94SStefano Zampini   }
40709d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
40719d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4072e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4073e7931f94SStefano Zampini 
4074e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4075e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4076e7931f94SStefano 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) */
4077e7931f94SStefano Zampini   if (n_recvs) {
407828143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4079e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4080e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4081e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4082e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4083e7931f94SStefano Zampini         break;
4084e7931f94SStefano Zampini       }
4085e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4086e7931f94SStefano Zampini     }
4087e7931f94SStefano Zampini     switch (new_local_type_private) {
408828143c3dSStefano Zampini       case MATDENSE_PRIVATE:
408928143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4090e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4091e7931f94SStefano Zampini           bs = 1;
409228143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
409328143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
409428143c3dSStefano Zampini           bs = 1;
409528143c3dSStefano Zampini         }
4096e7931f94SStefano Zampini         break;
4097e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4098e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4099e7931f94SStefano Zampini         bs = 1;
4100e7931f94SStefano Zampini         break;
4101e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4102e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4103e7931f94SStefano Zampini         break;
4104e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4105e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4106e7931f94SStefano Zampini         break;
4107e7931f94SStefano Zampini       default:
41089d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4109e7931f94SStefano Zampini         break;
4110e7931f94SStefano Zampini     }
411128143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
411228143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
411328143c3dSStefano Zampini     bs = 1;
4114e7931f94SStefano Zampini   }
4115e7931f94SStefano Zampini 
411670cf5478SStefano Zampini   /* create MATIS object if needed */
411770cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4118e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4119e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
412070cf5478SStefano Zampini   } else {
412170cf5478SStefano Zampini     /* it also destroys the local matrices */
412270cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
412370cf5478SStefano Zampini   }
412470cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4125e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
41269d30be91SStefano Zampini 
41279d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
41289d30be91SStefano Zampini 
41299d30be91SStefano Zampini   /* Global to local map of received indices */
41309d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
41319d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
41329d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
41339d30be91SStefano Zampini 
41349d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
41359d30be91SStefano Zampini   buf_size_idxs = 0;
41369d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
41379d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
41389d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
41399d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
41409d30be91SStefano Zampini   }
41419d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
41429d30be91SStefano Zampini 
41439d30be91SStefano Zampini   /* set preallocation */
41449d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
41459d30be91SStefano Zampini   if (!newisdense) {
41469d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
41479d30be91SStefano Zampini 
41489d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
41499d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
41509d30be91SStefano Zampini     if (n_recvs) {
41519d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
41529d30be91SStefano Zampini     }
41539d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
41549d30be91SStefano Zampini       PetscInt j;
41559d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
41569d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
41579d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
41589d30be91SStefano Zampini         }
41599d30be91SStefano Zampini       } else {
41609d30be91SStefano Zampini         /* TODO */
41619d30be91SStefano Zampini       }
41629d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
41639d30be91SStefano Zampini     }
41649d30be91SStefano Zampini     if (new_local_nnz) {
41659d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
41669d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
41679d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
41689d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
41699d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
41709d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
41719d30be91SStefano Zampini     } else {
41729d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
41739d30be91SStefano Zampini     }
41749d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
41759d30be91SStefano Zampini   } else {
41769d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
41779d30be91SStefano Zampini   }
4178e7931f94SStefano Zampini 
4179e7931f94SStefano Zampini   /* set values */
4180e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
41819d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
4182e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4183e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
4184e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
41859d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
4186e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4187e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4188e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
418928143c3dSStefano Zampini     } else {
419028143c3dSStefano Zampini       /* TODO */
4191e7931f94SStefano Zampini     }
4192e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4193e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
4194e7931f94SStefano Zampini   }
4195e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4196e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
419770cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
419870cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
41999d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
42009d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
4201e7931f94SStefano Zampini 
4202dfd14d43SStefano Zampini #if 0
420328143c3dSStefano Zampini   if (!restrict_comm) { /* check */
4204e7931f94SStefano Zampini     Vec       lvec,rvec;
4205e7931f94SStefano Zampini     PetscReal infty_error;
4206e7931f94SStefano Zampini 
42072a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
4208e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
4209e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
4210e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
421170cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
4212e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4213e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
4214e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
4215e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
4216e7931f94SStefano Zampini   }
421728143c3dSStefano Zampini #endif
4218e7931f94SStefano Zampini 
421928143c3dSStefano Zampini   /* assemble new additional is (if any) */
422028143c3dSStefano Zampini   if (nis) {
422128143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
422228143c3dSStefano Zampini 
422328143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4224854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
422528143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
422628143c3dSStefano Zampini     psum = 0;
422728143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
422828143c3dSStefano Zampini       for (j=0;j<nis;j++) {
422928143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
423028143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
423128143c3dSStefano Zampini         psum += plen;
423228143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
423328143c3dSStefano Zampini       }
423428143c3dSStefano Zampini     }
4235854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
4236854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
423728143c3dSStefano Zampini     for (i=1;i<nis;i++) {
423828143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
423928143c3dSStefano Zampini     }
424028143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
424128143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
424228143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
424328143c3dSStefano Zampini       for (j=0;j<nis;j++) {
424428143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
424528143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
424628143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
424728143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
424828143c3dSStefano Zampini       }
424928143c3dSStefano Zampini     }
425028143c3dSStefano Zampini     for (i=0;i<nis;i++) {
425128143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
425228143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
425328143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
425428143c3dSStefano Zampini     }
425528143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
425628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
425728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
425828143c3dSStefano Zampini   }
4259e7931f94SStefano Zampini   /* free workspace */
426028143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4261e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4262e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4263e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4264e7931f94SStefano Zampini   if (isdense) {
4265e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4266e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4267e7931f94SStefano Zampini   } else {
4268e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4269e7931f94SStefano Zampini   }
427028143c3dSStefano Zampini   if (nis) {
427128143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
427228143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
427328143c3dSStefano Zampini   }
4274e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4275e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
427628143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4277e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4278e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
427928143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4280e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4281e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4282e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4283e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4284e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
428528143c3dSStefano Zampini   if (nis) {
428628143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
428728143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
428828143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
428928143c3dSStefano Zampini   }
429028143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
429128143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
429228143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
429328143c3dSStefano Zampini     for (i=0;i<nis;i++) {
429428143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
429528143c3dSStefano Zampini     }
429653a05cb3SStefano Zampini     *mat_n = NULL;
429728143c3dSStefano Zampini   }
4298e7931f94SStefano Zampini   PetscFunctionReturn(0);
4299e7931f94SStefano Zampini }
4300a57a6d2fSStefano Zampini 
430112edc857SStefano Zampini /* temporary hack into ksp private data structure */
4302af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
430312edc857SStefano Zampini 
4304c8587f34SStefano Zampini #undef __FUNCT__
4305c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4306c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4307c8587f34SStefano Zampini {
4308c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4309c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
431020a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
43119881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
431220a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
43136e683305SStefano Zampini   IS                     coarse_is,*isarray;
43146e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
43156e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
4316f9eb5b7dSStefano Zampini   PC                     pc_temp;
4317c8587f34SStefano Zampini   PCType                 coarse_pc_type;
4318c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
4319f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
43204f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
43216e683305SStefano Zampini   Mat                    t_coarse_mat_is;
43226e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
43236e683305SStefano Zampini   PetscMPIInt            all_procs;
432474e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
432568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
432622bc73bbSStefano Zampini   PetscScalar            *array;
43279881197aSStefano Zampini   PetscErrorCode         ierr;
4328fdc09c96SStefano Zampini 
4329c8587f34SStefano Zampini   PetscFunctionBegin;
4330c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
433168457ee5SStefano 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 */
4332fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
43335a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
4334fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
4335f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4336f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4337f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
4338fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
433951bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
434051bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4341dc4bcba2SStefano Zampini         PC        pc;
4342dc4bcba2SStefano Zampini         PetscBool isbddc;
4343dc4bcba2SStefano Zampini 
4344dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
4345dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4346dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4347dc4bcba2SStefano Zampini         if (isbddc) {
4348dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4349dc4bcba2SStefano Zampini         }
4350727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4351fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
4352fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
4353fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
4354f4ddd8eeSStefano Zampini       }
4355fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4356fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
4357f4ddd8eeSStefano Zampini     }
435870cf5478SStefano Zampini     /* reset any subassembling information */
435970cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
43606e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
43616e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4362fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
4363f4ddd8eeSStefano Zampini   }
4364c8587f34SStefano Zampini 
43656e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
43662b510759SStefano Zampini   im_active = !!(pcis->n);
43672b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
43686e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
43696e683305SStefano Zampini   void_procs = all_procs-active_procs;
43706e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
437174e2c79eSStefano Zampini   redist = PETSC_FALSE;
437222bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
43736e683305SStefano Zampini     csin_ml = PETSC_TRUE;
43746e683305SStefano Zampini     ncoarse_ml = void_procs;
4375779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4376779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
43776e683305SStefano Zampini       csin_ds = PETSC_TRUE;
437818a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
437918a45a71SStefano Zampini       redist = PETSC_TRUE;
438018a45a71SStefano Zampini     } else {
43816e683305SStefano Zampini       csin_ds = PETSC_TRUE;
4382779c1cceSStefano Zampini       ncoarse_ds = active_procs;
4383779c1cceSStefano Zampini       redist = PETSC_TRUE;
438418a45a71SStefano Zampini     }
43856e683305SStefano Zampini   } else {
43866e683305SStefano Zampini     csin_ml = PETSC_FALSE;
43876e683305SStefano Zampini     ncoarse_ml = all_procs;
43886e683305SStefano Zampini     if (void_procs) {
43896e683305SStefano Zampini       csin_ds = PETSC_TRUE;
43906e683305SStefano Zampini       ncoarse_ds = void_procs;
43916e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
43926e683305SStefano Zampini     } else {
4393779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
439474e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
439574e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
439674e2c79eSStefano Zampini         redist = PETSC_TRUE;
439774e2c79eSStefano Zampini       } else {
43986e683305SStefano Zampini         csin_ds = PETSC_FALSE;
43996e683305SStefano Zampini         ncoarse_ds = all_procs;
44006e683305SStefano Zampini       }
44016e683305SStefano Zampini     }
440274e2c79eSStefano Zampini   }
44036e683305SStefano Zampini 
44046e683305SStefano Zampini   /*
44056e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
44066e683305SStefano Zampini     - we have not exceeded the number of levels requested
44076e683305SStefano Zampini     - we can actually subassemble the active processes
44086e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
44096e683305SStefano Zampini   */
44106e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
44116e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
44126e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
44136e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
44146e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4415f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
44162b510759SStefano Zampini     } else {
4417f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
4418c8587f34SStefano Zampini     }
4419c8587f34SStefano Zampini   }
44206e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
44216e683305SStefano Zampini   if (multilevel_allowed) {
44226e683305SStefano Zampini     ncoarse = ncoarse_ml;
44236e683305SStefano Zampini     csin = csin_ml;
442458da7f69SStefano Zampini     redist = PETSC_FALSE;
44256e683305SStefano Zampini   } else {
44266e683305SStefano Zampini     ncoarse = ncoarse_ds;
44276e683305SStefano Zampini     csin = csin_ds;
44286e683305SStefano Zampini   }
4429e7931f94SStefano Zampini 
4430abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
4431abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4432abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4433abbbba34SStefano Zampini 
4434abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
443522bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
443622bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
443722bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
443822bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4439b1ecc7b1SStefano Zampini #if 0
4440b9b85e73SStefano Zampini   {
4441b9b85e73SStefano Zampini     PetscViewer viewer;
4442b9b85e73SStefano Zampini     char filename[256];
4443b1ecc7b1SStefano Zampini     sprintf(filename,"local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4444b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4445b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4446b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
4447b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4448b9b85e73SStefano Zampini   }
4449b9b85e73SStefano Zampini #endif
4450e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)pc),1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_islg,NULL,&t_coarse_mat_is);CHKERRQ(ierr);
44516e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
44526e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
44536e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4454abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4455abbbba34SStefano Zampini 
44566e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
44576e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
44586e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
44596e683305SStefano Zampini     const PetscInt         *idxs;
44606e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
44616e683305SStefano Zampini 
44626e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
44630be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
44646e683305SStefano Zampini     /* allocate space for temporary storage */
4465854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4466854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
44676e683305SStefano Zampini     /* allocate for IS array */
44686e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
44696e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
44706e683305SStefano Zampini     nis = nisdofs + nisneu;
4471854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
44726e683305SStefano Zampini     /* dofs splitting */
44736e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
44746e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
44756e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
44766e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
44776e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
44786e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
44796e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
44806e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
44816e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
44826e683305SStefano Zampini     }
44836e683305SStefano Zampini     /* neumann boundaries */
44846e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
44856e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
44866e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
44876e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
44886e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
44896e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
44906e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
44916e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
44926e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
44936e683305SStefano Zampini     }
44946e683305SStefano Zampini     /* free memory */
44956e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
44966e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
44976e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
44986e683305SStefano Zampini   } else {
44996e683305SStefano Zampini     nis = 0;
45006e683305SStefano Zampini     nisdofs = 0;
45016e683305SStefano Zampini     nisneu = 0;
45026e683305SStefano Zampini     isarray = NULL;
45036e683305SStefano Zampini   }
45046e683305SStefano Zampini   /* destroy no longer needed map */
45056e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
45066e683305SStefano Zampini 
45076e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
45086e683305SStefano Zampini   coarse_mat_is = NULL;
45096e683305SStefano Zampini   if (csin) {
45106e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
451174e2c79eSStefano Zampini       if (redist) {
451274e2c79eSStefano Zampini         PetscMPIInt rank;
4513779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
451474e2c79eSStefano Zampini 
451574e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
451658da7f69SStefano Zampini         spc = active_procs/ncoarse;
451758da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
4518779c1cceSStefano Zampini         if (im_active) {
4519779c1cceSStefano Zampini           destsize = 1;
452074e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
452174e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
452274e2c79eSStefano Zampini           } else {
452374e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
452474e2c79eSStefano Zampini           }
452574e2c79eSStefano Zampini         } else {
4526779c1cceSStefano Zampini           destsize = 0;
45276e683305SStefano Zampini         }
4528779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4529779c1cceSStefano Zampini       } else if (csin_type_simple) {
45306e683305SStefano Zampini         PetscMPIInt rank;
45316e683305SStefano Zampini         PetscInt    issize,isidx;
4532779c1cceSStefano Zampini 
45336e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
45346e683305SStefano Zampini         if (im_active) {
45356e683305SStefano Zampini           issize = 1;
45366e683305SStefano Zampini           isidx = (PetscInt)rank;
45376e683305SStefano Zampini         } else {
45386e683305SStefano Zampini           issize = 0;
45396e683305SStefano Zampini           isidx = -1;
45406e683305SStefano Zampini         }
45416e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4542779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
4543b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
45446e683305SStefano Zampini       }
4545779c1cceSStefano Zampini 
4546779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
4547779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
4548779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
4549779c1cceSStefano Zampini         PetscInt *coarse_candidates;
4550779c1cceSStefano Zampini         const PetscInt* tisindices;
4551779c1cceSStefano Zampini 
4552779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
4553779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
4554779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4555779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
4556779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
4557779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
4558779c1cceSStefano Zampini           }
4559779c1cceSStefano Zampini         }
4560779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
4561779c1cceSStefano Zampini 
4562779c1cceSStefano Zampini 
45636e683305SStefano Zampini         if (pcbddc->dbg_flag) {
45646e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
45656e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
45666e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
45676e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
4568779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
45696e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
45706e683305SStefano Zampini           }
45716e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
45726e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
45736e683305SStefano Zampini         }
45746e683305SStefano Zampini         /* shift the pattern on coarse candidates */
45756e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
45766e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
4577854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
45786e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
45796e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
45806e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
45816e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
45826e683305SStefano Zampini       }
45836e683305SStefano Zampini       if (pcbddc->dbg_flag) {
45846e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
45856e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
45866e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
45876e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
45886e683305SStefano Zampini       }
4589779c1cceSStefano Zampini     }
45906e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
459153a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
459253a05cb3SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,PETSC_FALSE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
459353a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
459453a05cb3SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
459553a05cb3SStefano Zampini     }
45966e683305SStefano Zampini   } else {
45976e683305SStefano Zampini     if (pcbddc->dbg_flag) {
45986e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
45996e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
46006e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
46016e683305SStefano Zampini     }
46026e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
46036e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
46046e683305SStefano Zampini   }
46056e683305SStefano Zampini 
46066e683305SStefano Zampini   /* create local to global scatters for coarse problem */
460768457ee5SStefano Zampini   if (compute_vecs) {
46086e683305SStefano Zampini     PetscInt lrows;
46096e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
46106e683305SStefano Zampini     if (coarse_mat_is) {
46116e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
46126e683305SStefano Zampini     } else {
46136e683305SStefano Zampini       lrows = 0;
46146e683305SStefano Zampini     }
46156e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
46166e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
46176e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
46186e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
46196e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
46206e683305SStefano Zampini   }
46216e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
46226e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
4623c8587f34SStefano Zampini 
4624f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
4625f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
4626f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
4627f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
4628f9eb5b7dSStefano Zampini   } else {
4629f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
4630f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
4631c8587f34SStefano Zampini   }
4632c8587f34SStefano Zampini 
46336e683305SStefano Zampini   /* print some info if requested */
46346e683305SStefano Zampini   if (pcbddc->dbg_flag) {
46356e683305SStefano Zampini     if (!multilevel_allowed) {
46366e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
46376e683305SStefano Zampini       if (multilevel_requested) {
46386e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Not enough active processes on level %d (active processes %d, coarsening ratio %d)\n",pcbddc->current_level,active_procs,pcbddc->coarsening_ratio);CHKERRQ(ierr);
46396e683305SStefano Zampini       } else if (pcbddc->max_levels) {
46406e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
46416e683305SStefano Zampini       }
46426e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
46436e683305SStefano Zampini     }
46446e683305SStefano Zampini   }
46456e683305SStefano Zampini 
4646f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
46476e683305SStefano Zampini   if (coarse_mat_is) {
46486e683305SStefano Zampini     MatReuse coarse_mat_reuse;
46496a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
46506e683305SStefano Zampini     if (pcbddc->dbg_flag) {
46516e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
46526e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
46536e683305SStefano Zampini     }
4654f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
4655312be037SStefano Zampini       char prefix[256],str_level[16];
4656e604994aSStefano Zampini       size_t len;
46576e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
4658422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
4659c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
4660f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
46615f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
4662c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
46636e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
4664c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4665c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4666e604994aSStefano Zampini       /* prefix */
4667e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
4668e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4669e604994aSStefano Zampini       if (!pcbddc->current_level) {
4670e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4671e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
4672c8587f34SStefano Zampini       } else {
4673e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4674312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4675312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
467634d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4677312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4678e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
4679e604994aSStefano Zampini       }
4680e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
46813e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
46823e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
46833e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
46843e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
4685f9eb5b7dSStefano Zampini       /* allow user customization */
4686f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
46873e3c6dadSStefano Zampini     }
46883e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
468951bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
46903e3c6dadSStefano Zampini     if (nisdofs) {
46913e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
46923e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
46933e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
46943e3c6dadSStefano Zampini       }
46953e3c6dadSStefano Zampini     }
46963e3c6dadSStefano Zampini     if (nisneu) {
46973e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
46983e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
4699312be037SStefano Zampini     }
4700f9eb5b7dSStefano Zampini 
4701f9eb5b7dSStefano Zampini     /* get some info after set from options */
4702f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
4703f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
47044f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
47056e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
4706f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4707f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
4708f9eb5b7dSStefano Zampini     }
470939f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
47104f3a063dSStefano Zampini     if (isredundant) {
47114f3a063dSStefano Zampini       KSP inner_ksp;
47124f3a063dSStefano Zampini       PC  inner_pc;
47134f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
47144f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
47154f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
47164f3a063dSStefano Zampini     }
4717f9eb5b7dSStefano Zampini 
4718f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
4719fa7f1dd8SStefano Zampini     if (coarse_reuse) {
472081d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
4721fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
47226e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
4723fa7f1dd8SStefano Zampini     } else {
47246e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
4725fa7f1dd8SStefano Zampini     }
4726c8587f34SStefano Zampini     if (isbddc || isnn) {
472722bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
472870cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
4729b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
473022b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
47316e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47326e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
47336e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
47346e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
473522b6e8a2SStefano Zampini           }
473670cf5478SStefano Zampini         }
473753a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
473870cf5478SStefano Zampini       } else {
473922bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
474022bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
474122bc73bbSStefano Zampini       }
474222bc73bbSStefano Zampini     } else {
47432e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
4744c8587f34SStefano Zampini     }
4745c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
4746c8587f34SStefano Zampini 
47473301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
47485a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
47493301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
47503301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
47513301b35fSStefano Zampini     }
47523301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
47533301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
47543301b35fSStefano Zampini     }
47553301b35fSStefano Zampini     if (pc->pmat->spd_set) {
47563301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
47573301b35fSStefano Zampini     }
47586e683305SStefano Zampini     /* set operators */
47595f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
47606e683305SStefano Zampini     if (pcbddc->dbg_flag) {
47616e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
47626e683305SStefano Zampini     }
47636e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
47646e683305SStefano Zampini     coarse_mat = 0;
47656e683305SStefano Zampini   }
47666e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
4767b1ecc7b1SStefano Zampini #if 0
4768b9b85e73SStefano Zampini   {
4769b9b85e73SStefano Zampini     PetscViewer viewer;
4770b9b85e73SStefano Zampini     char filename[256];
4771b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
4772b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
4773b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4774b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4775b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4776b9b85e73SStefano Zampini   }
4777b9b85e73SStefano Zampini #endif
4778c8587f34SStefano Zampini 
4779c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4780298c0119SStefano Zampini #if 0
4781c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4782c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
478398a51de6SStefano Zampini   }
4784298c0119SStefano Zampini #endif
478598a51de6SStefano Zampini 
478698a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
478798a51de6SStefano Zampini     Vec crhs,csol;
478898a51de6SStefano Zampini     PetscBool ispreonly;
478904708bb6SStefano Zampini 
479098a51de6SStefano Zampini     if (CoarseNullSpace) {
4791c8587f34SStefano Zampini       if (isbddc) {
4792c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4793c8587f34SStefano Zampini       } else {
47945fa7ec2dSBarry Smith         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
4795c8587f34SStefano Zampini       }
4796c8587f34SStefano Zampini     }
4797f9eb5b7dSStefano Zampini     /* setup coarse ksp */
4798f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4799f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4800f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
48016e683305SStefano Zampini     /* hack */
4802f347579bSStefano Zampini     if (!csol) {
48032a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4804f9eb5b7dSStefano Zampini     }
4805f347579bSStefano Zampini     if (!crhs) {
48062a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4807f347579bSStefano Zampini     }
4808cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4809cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
48106e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4811c8587f34SStefano Zampini       KSP       check_ksp;
48122b510759SStefano Zampini       KSPType   check_ksp_type;
4813c8587f34SStefano Zampini       PC        check_pc;
48146e683305SStefano Zampini       Vec       check_vec,coarse_vec;
48156a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
48162b510759SStefano Zampini       PetscInt  its;
48176e683305SStefano Zampini       PetscBool compute_eigs;
48186e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
48196e683305SStefano Zampini       PetscInt  neigs;
48208e185a42SStefano Zampini       const char *prefix;
4821c8587f34SStefano Zampini 
48222b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
48236e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
4824422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
482523ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4826f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
48272b510759SStefano Zampini       if (ispreonly) {
48282b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
48296e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
48302b510759SStefano Zampini       } else {
4831cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
48326e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4833c8587f34SStefano Zampini       }
4834c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
48356e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
48366e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
48376e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4838a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4839a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4840a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4841a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4842c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4843c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4844c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4845c8587f34SStefano Zampini       /* create random vec */
48466e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
48476e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
4848c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
4849c8587f34SStefano Zampini       if (CoarseNullSpace) {
4850c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
4851c8587f34SStefano Zampini       }
48526e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
4853c8587f34SStefano Zampini       /* solve coarse problem */
48546e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
4855c8587f34SStefano Zampini       if (CoarseNullSpace) {
48566e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
4857c8587f34SStefano Zampini       }
4858cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
48596e683305SStefano Zampini       if (compute_eigs) {
4860854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4861854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
48626e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
48636e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
48646e683305SStefano Zampini         lambda_min = eigs_r[0];
48656e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
48666e683305SStefano Zampini           if (lambda_max>lambda_min) {
4867cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4868cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4869cbcc2c2aSStefano Zampini           }
4870c8587f34SStefano Zampini         }
4871c8587f34SStefano Zampini       }
4872cbcc2c2aSStefano Zampini 
4873c8587f34SStefano Zampini       /* check coarse problem residual error */
48746e683305SStefano Zampini       if (pcbddc->dbg_flag) {
48756e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
48766e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
48776e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4878c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
48796e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
48806e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4881c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
4882779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
48836e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
48846e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
48856e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
48866e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
48876e683305SStefano Zampini         if (compute_eigs) {
48886e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4889deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4890c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
48916e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
48926e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem eigenvalues (estimated with %d iterations of %s): %1.6e %1.6e (%1.6e %1.6e)\n",its,check_ksp_type,lambda_min,lambda_max,lambda_min_s,lambda_max_s);CHKERRQ(ierr);
48936e683305SStefano Zampini           for (i=0;i<neigs;i++) {
48946e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4895c8587f34SStefano Zampini           }
48966e683305SStefano Zampini         }
48976e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
48986e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
48996e683305SStefano Zampini       }
4900c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
49016e683305SStefano Zampini       if (compute_eigs) {
49026e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
49036e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4904c8587f34SStefano Zampini       }
49056e683305SStefano Zampini     }
49066e683305SStefano Zampini   }
4907cbcc2c2aSStefano Zampini   /* print additional info */
4908cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
49096e683305SStefano Zampini     /* waits until all processes reaches this point */
49106e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4911cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4912cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4913cbcc2c2aSStefano Zampini   }
4914cbcc2c2aSStefano Zampini 
49152b510759SStefano Zampini   /* free memory */
4916c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4917fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4918c8587f34SStefano Zampini   PetscFunctionReturn(0);
4919c8587f34SStefano Zampini }
4920674ae819SStefano Zampini 
4921f34684f1SStefano Zampini #undef __FUNCT__
4922f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4923f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4924f34684f1SStefano Zampini {
4925f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4926f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
4927f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
4928dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
4929dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
493073be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
4931dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
4932f34684f1SStefano Zampini   PetscErrorCode ierr;
4933f34684f1SStefano Zampini 
4934f34684f1SStefano Zampini   PetscFunctionBegin;
4935f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
49360e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
49370e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
4938727cdba6SStefano Zampini   }
4939dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
49403bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
4941dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
4942dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
4943dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
4944dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
4945dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
4946dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
49470e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
49480e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
49490e6343abSStefano Zampini   }
4950dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
4951dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
4952dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
4953dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
4954dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
4955f34684f1SStefano Zampini 
4956f34684f1SStefano Zampini   /* check numbering */
4957f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
4958019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
4959dc456d91SStefano Zampini     PetscInt    i;
4960b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
4961f34684f1SStefano Zampini 
4962f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4963f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4964f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
49650fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
4966019a44ceSStefano Zampini     /* counter */
4967019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4968019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4969019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4970019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4971019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4972019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4973019a44ceSStefano Zampini 
4974f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4975f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4976727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4977f34684f1SStefano Zampini     }
4978f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4979f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4980f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4981e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4982e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4983e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4984e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4985f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4986019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
4987f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4988019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
4989019a44ceSStefano Zampini         PetscInt owned = (PetscInt)(array[i]);
4990019a44ceSStefano Zampini         PetscInt neigh = (PetscInt)(array2[i]);
4991b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
4992019a44ceSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a %d processes instead of %d!\n",PetscGlobalRank,i,owned,neigh);CHKERRQ(ierr);
4993f34684f1SStefano Zampini       }
4994f34684f1SStefano Zampini     }
4995019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
4996b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4997f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4998f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4999f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5000f34684f1SStefano Zampini     }
5001f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5002f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5003e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5004e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5005f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5006f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5007b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5008ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5009ca8b9ea9SStefano Zampini 
5010ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
50113bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5012f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5013f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5014f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5015f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
50164bc2dc4bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d,%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i],gidxs[i]);CHKERRQ(ierr);
5017f34684f1SStefano Zampini       }
5018f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5019ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5020f34684f1SStefano Zampini     }
5021f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5022302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5023f34684f1SStefano Zampini   }
50248bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5025f34684f1SStefano Zampini   /* get back data */
5026f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5027f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5028674ae819SStefano Zampini   PetscFunctionReturn(0);
5029674ae819SStefano Zampini }
5030674ae819SStefano Zampini 
5031e456f2a8SStefano Zampini #undef __FUNCT__
5032e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5033a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5034e456f2a8SStefano Zampini {
5035e456f2a8SStefano Zampini   IS             localis_t;
5036a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5037e456f2a8SStefano Zampini   PetscScalar    *vals;
5038e456f2a8SStefano Zampini   PetscErrorCode ierr;
5039e456f2a8SStefano Zampini 
5040e456f2a8SStefano Zampini   PetscFunctionBegin;
5041a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5042e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5043854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5044e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5045e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5046a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5047a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
50481035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5049a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
50501035eff8SStefano Zampini   }
5051a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5052e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5053e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5054a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5055a7dc3881SStefano Zampini   /* now compute set in local ordering */
5056a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5057a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5058a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5059a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5060a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5061ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5062e456f2a8SStefano Zampini       lsize++;
5063e456f2a8SStefano Zampini     }
5064e456f2a8SStefano Zampini   }
5065854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5066a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5067ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5068e456f2a8SStefano Zampini       idxs[lsize++] = i;
5069e456f2a8SStefano Zampini     }
5070e456f2a8SStefano Zampini   }
5071a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5072a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5073e456f2a8SStefano Zampini   *localis = localis_t;
5074e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5075e456f2a8SStefano Zampini }
5076906d46d4SStefano Zampini 
5077906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5078906d46d4SStefano Zampini #undef __FUNCT__
5079906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5080906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5081906d46d4SStefano Zampini {
5082906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5083906d46d4SStefano Zampini   PetscErrorCode   ierr;
5084906d46d4SStefano Zampini 
5085906d46d4SStefano Zampini   PetscFunctionBegin;
5086906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5087906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5088906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5089906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5090906d46d4SStefano Zampini   PetscFunctionReturn(0);
5091906d46d4SStefano Zampini }
5092906d46d4SStefano Zampini 
5093906d46d4SStefano Zampini #undef __FUNCT__
5094906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5095906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5096906d46d4SStefano Zampini {
5097906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5098906d46d4SStefano Zampini   PetscErrorCode   ierr;
5099906d46d4SStefano Zampini 
5100906d46d4SStefano Zampini   PetscFunctionBegin;
5101906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5102906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5103906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5104906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5105906d46d4SStefano Zampini   PetscFunctionReturn(0);
5106906d46d4SStefano Zampini }
5107b96c3477SStefano Zampini 
5108b96c3477SStefano Zampini #undef __FUNCT__
5109b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
511008122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5111b96c3477SStefano Zampini {
5112a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5113b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5114b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5115a64f4aa4SStefano Zampini   Mat                 S_j;
5116b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
5117b96c3477SStefano Zampini   PetscBool           free_used_adj;
5118b96c3477SStefano Zampini   PetscErrorCode      ierr;
5119b96c3477SStefano Zampini 
5120b96c3477SStefano Zampini   PetscFunctionBegin;
5121b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
5122b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
512308122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
5124b96c3477SStefano Zampini     used_xadj = NULL;
5125b96c3477SStefano Zampini     used_adjncy = NULL;
5126b96c3477SStefano Zampini   } else {
512708122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
512808122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
512908122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
513008122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
5131b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
5132b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
5133b96c3477SStefano Zampini     } else {
51342fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
5135b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
5136b96c3477SStefano Zampini       PetscInt       nvtxs;
5137b96c3477SStefano Zampini 
51382fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
51392fffb893SStefano Zampini       if (flg_row) {
5140b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
5141b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
5142b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
5143b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
51442fffb893SStefano Zampini       } else {
51452fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
51462fffb893SStefano Zampini         used_xadj = NULL;
51472fffb893SStefano Zampini         used_adjncy = NULL;
51482fffb893SStefano Zampini       }
51492fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5150b96c3477SStefano Zampini     }
5151b96c3477SStefano Zampini   }
5152d5574798SStefano Zampini 
5153d5574798SStefano Zampini   /* setup sub_schurs data */
5154a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5155a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
5156a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
5157a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
515806a4e24aSStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,NULL,S_j,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->faster_deluxe,pcbddc->adaptive_selection,PETSC_FALSE,PETSC_FALSE);CHKERRQ(ierr);
5159a64f4aa4SStefano Zampini   } else {
51606816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
516104708bb6SStefano Zampini     PetscBool isseqaij;
51625feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
51635feab87aSStefano Zampini       PetscInt n_vertices;
51645feab87aSStefano Zampini 
51655feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
51662034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
51675feab87aSStefano Zampini     }
516804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
516904708bb6SStefano Zampini     if (!isseqaij) {
517004708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
517104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
517204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
517304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
517404708bb6SStefano Zampini       } else {
517504708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
517604708bb6SStefano Zampini       }
517704708bb6SStefano Zampini     }
517806a4e24aSStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,pcbddc->local_mat,S_j,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->faster_deluxe,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point);CHKERRQ(ierr);
5179a64f4aa4SStefano Zampini   }
5180a64f4aa4SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5181b96c3477SStefano Zampini 
5182b96c3477SStefano Zampini   /* free adjacency */
5183b96c3477SStefano Zampini   if (free_used_adj) {
5184b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
5185b96c3477SStefano Zampini   }
5186b96c3477SStefano Zampini   PetscFunctionReturn(0);
5187b96c3477SStefano Zampini }
5188b96c3477SStefano Zampini 
5189b96c3477SStefano Zampini #undef __FUNCT__
5190b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
519108122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
5192b96c3477SStefano Zampini {
5193b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5194b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5195b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5196b96c3477SStefano Zampini   PCBDDCGraph         graph;
5197b96c3477SStefano Zampini   PetscErrorCode      ierr;
5198b96c3477SStefano Zampini 
5199b96c3477SStefano Zampini   PetscFunctionBegin;
5200b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
520108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
52023301b35fSStefano Zampini     IS       verticesIS,verticescomm;
52033301b35fSStefano Zampini     PetscInt vsize,*idxs;
5204b96c3477SStefano Zampini 
5205b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
52063301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
52073301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
52083301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
52093301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
52103301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
5211b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
52127fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
52133301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
52143301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
5215b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5216b96c3477SStefano Zampini /*
5217b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
5218b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5219b96c3477SStefano Zampini     }
5220b96c3477SStefano Zampini */
5221b96c3477SStefano Zampini   } else {
5222b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
5223b96c3477SStefano Zampini   }
5224b96c3477SStefano Zampini 
5225b96c3477SStefano Zampini   /* sub_schurs init */
5226a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
5227a64f4aa4SStefano Zampini 
5228b96c3477SStefano Zampini   /* free graph struct */
522908122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
5230b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
5231b96c3477SStefano Zampini   }
5232b96c3477SStefano Zampini   PetscFunctionReturn(0);
5233b96c3477SStefano Zampini }
5234