xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 06a4e24a4ea34074cd1dc021a3bf2cd6abf1fe12)
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__
9c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
10c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
11c263805aSStefano Zampini {
12c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
13c263805aSStefano Zampini   const PetscInt *idxs;
14c263805aSStefano Zampini   PetscInt       nz = 0;
15c263805aSStefano Zampini   PetscErrorCode ierr;
16c263805aSStefano Zampini 
17c263805aSStefano Zampini   PetscFunctionBegin;
18c263805aSStefano Zampini   if (!pcbddc->zerodiag) {
19c263805aSStefano Zampini     PetscFunctionReturn(0);
20c263805aSStefano Zampini   } else {
21c263805aSStefano Zampini     ierr = ISGetLocalSize(pcbddc->zerodiag,&nz);CHKERRQ(ierr);
22c263805aSStefano Zampini     if (!nz) PetscFunctionReturn(0);
23c263805aSStefano Zampini   }
24c263805aSStefano Zampini   ierr = ISGetIndices(pcbddc->zerodiag,&idxs);CHKERRQ(ierr);
25c263805aSStefano Zampini   /* TODO: add error checking
26c263805aSStefano Zampini     - avoid nested pop (or push) calls.
27c263805aSStefano Zampini     - cannot push before pop.
28c263805aSStefano Zampini   */
29c263805aSStefano Zampini   if (pop) {
30c263805aSStefano Zampini     const PetscInt    *cB0_cols;
31c263805aSStefano Zampini     PetscInt          cB0_ncol;
32c263805aSStefano Zampini     const PetscScalar *cB0_vals;
33c263805aSStefano Zampini 
34c263805aSStefano Zampini     /* extract B_0 */
35c263805aSStefano Zampini     ierr = MatGetRow(pcbddc->local_mat,idxs[nz-1],&cB0_ncol,&cB0_cols,&cB0_vals);CHKERRQ(ierr);
36c263805aSStefano Zampini     pcbddc->B0_ncol = cB0_ncol;
37c263805aSStefano Zampini     ierr = PetscFree2(pcbddc->B0_cols,pcbddc->B0_vals);CHKERRQ(ierr);
38c263805aSStefano Zampini     ierr = PetscMalloc2(cB0_ncol,&pcbddc->B0_cols,cB0_ncol,&pcbddc->B0_vals);CHKERRQ(ierr);
39c263805aSStefano Zampini     ierr = PetscMemcpy(pcbddc->B0_cols,cB0_cols,cB0_ncol*sizeof(PetscInt));CHKERRQ(ierr);
40c263805aSStefano Zampini     ierr = PetscMemcpy(pcbddc->B0_vals,cB0_vals,cB0_ncol*sizeof(PetscScalar));CHKERRQ(ierr);
41c263805aSStefano Zampini     ierr = MatRestoreRow(pcbddc->local_mat,idxs[nz-1],&cB0_ncol,&cB0_cols,&cB0_vals);CHKERRQ(ierr);
42c263805aSStefano Zampini     /* remove rows and cols from local problem */
43c263805aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
44c263805aSStefano Zampini     ierr = MatZeroRowsColumns(pcbddc->local_mat,1,idxs+nz-1,1.,NULL,NULL);CHKERRQ(ierr);
45c263805aSStefano Zampini   } else { /* push */
46c263805aSStefano Zampini     ierr = MatSetValues(pcbddc->local_mat,1,&idxs[nz-1],pcbddc->B0_ncol,pcbddc->B0_cols,pcbddc->B0_vals,INSERT_VALUES);CHKERRQ(ierr);
47c263805aSStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
48c263805aSStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49c263805aSStefano Zampini   }
50c263805aSStefano Zampini   PetscFunctionReturn(0);
51c263805aSStefano Zampini }
52c263805aSStefano Zampini 
53c263805aSStefano Zampini #undef __FUNCT__
54b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
5508122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
56b1b3d7a2SStefano Zampini {
57b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
5808122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5908122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
6008122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
6108122e43SStefano Zampini   PetscScalar     *work,lwork;
6208122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
6308122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
6408122e43SStefano Zampini   PetscReal       *eigs,thresh;
651b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
66f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
6708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
6808122e43SStefano Zampini   PetscReal       *rwork;
6908122e43SStefano Zampini #endif
70b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
71b1b3d7a2SStefano Zampini 
72b1b3d7a2SStefano Zampini   PetscFunctionBegin;
7308122e43SStefano Zampini   if (!sub_schurs->use_mumps) {
7408122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
7508122e43SStefano Zampini   }
7608122e43SStefano Zampini 
77*06a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
78*06a4e24aSStefano 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);
79*06a4e24aSStefano Zampini   }
80*06a4e24aSStefano Zampini 
81fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
82fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
83fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
84fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
85fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
86fd14bc51SStefano Zampini   }
87fd14bc51SStefano Zampini 
88e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
89e496cd5dSStefano 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);
90e496cd5dSStefano Zampini   }
91e496cd5dSStefano Zampini 
9208122e43SStefano Zampini   /* max size of subsets */
9308122e43SStefano Zampini   mss = 0;
9408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
9508122e43SStefano Zampini     PetscInt subset_size;
96862806e4SStefano Zampini 
9708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
9808122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
9908122e43SStefano Zampini   }
10008122e43SStefano Zampini 
10108122e43SStefano Zampini   /* min/max and threshold */
10208122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
103f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
10408122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
105f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
106f6f667cfSStefano Zampini   if (nmin) {
107f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
108f6f667cfSStefano Zampini   }
10908122e43SStefano Zampini 
11008122e43SStefano Zampini   /* allocate lapack workspace */
11108122e43SStefano Zampini   cum = cum2 = 0;
11208122e43SStefano Zampini   maxneigs = 0;
11308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
11408122e43SStefano Zampini     PetscInt n,subset_size;
115f6f667cfSStefano Zampini 
11608122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
11708122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
1189162d606SStefano Zampini     cum += subset_size;
1199162d606SStefano Zampini     cum2 += subset_size*n;
12008122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
12108122e43SStefano Zampini   }
12208122e43SStefano Zampini   if (mss) {
1239ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
12408122e43SStefano Zampini       PetscBLASInt B_itype = 1;
12508122e43SStefano Zampini       PetscBLASInt B_N = mss;
1264c6709b3SStefano Zampini       PetscReal    zero = 0.0;
1274c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
12808122e43SStefano Zampini 
12908122e43SStefano Zampini       B_lwork = -1;
13008122e43SStefano Zampini       S = NULL;
13108122e43SStefano Zampini       St = NULL;
132a58a30b4SStefano Zampini       eigs = NULL;
133a58a30b4SStefano Zampini       eigv = NULL;
134a58a30b4SStefano Zampini       B_iwork = NULL;
135a58a30b4SStefano Zampini       B_ifail = NULL;
136d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
137d1710679SStefano Zampini       rwork = NULL;
138d1710679SStefano Zampini #endif
1398bec7fa6SStefano Zampini       thresh = 1.0;
14008122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
14108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
14208122e43SStefano 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));
14308122e43SStefano Zampini #else
14408122e43SStefano 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));
14508122e43SStefano Zampini #endif
14608122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
14708122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
14808122e43SStefano Zampini     } else {
14908122e43SStefano Zampini         /* TODO */
15008122e43SStefano Zampini     }
15108122e43SStefano Zampini   } else {
15208122e43SStefano Zampini     lwork = 0;
15308122e43SStefano Zampini   }
15408122e43SStefano Zampini 
15508122e43SStefano Zampini   nv = 0;
156d62866d3SStefano 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) */
157d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
15808122e43SStefano Zampini   }
1594c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
160f6f667cfSStefano Zampini   if (allocated_S_St) {
161f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
162f6f667cfSStefano Zampini   }
163f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
16408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
16508122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
16608122e43SStefano Zampini #endif
1679162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
1689162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
1699162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
17008122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
1719162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
17208122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
17308122e43SStefano Zampini 
17408122e43SStefano Zampini   maxneigs = 0;
17508122e43SStefano Zampini   cum = cum2 = cumarray = 0;
1769162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
1779162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
178d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
17908122e43SStefano Zampini     const PetscInt *idxs;
18008122e43SStefano Zampini 
181d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
18208122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
18308122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
18408122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
18508122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
1869162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
1879162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
18808122e43SStefano Zampini     }
18908122e43SStefano Zampini     cum2 = cum;
190d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
19108122e43SStefano Zampini   }
19208122e43SStefano Zampini 
19308122e43SStefano Zampini   if (mss) { /* multilevel */
19408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
19508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
19608122e43SStefano Zampini   }
19708122e43SStefano Zampini 
19808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
19908122e43SStefano Zampini 
20008122e43SStefano Zampini     const PetscInt *idxs;
201f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
202862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
20308122e43SStefano Zampini     PetscBLASInt   B_N;
204aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
20508122e43SStefano Zampini 
206862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
207f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
208f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
2099ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
210aff50787SStefano Zampini         PetscInt j,k;
211aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
212aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
213aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
21408122e43SStefano Zampini         }
21508122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
216aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
217aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
218aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
219aff50787SStefano Zampini           }
22008122e43SStefano Zampini         }
22108122e43SStefano Zampini       } else {
22208122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
22308122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
22408122e43SStefano Zampini       }
2258bec7fa6SStefano Zampini     } else {
226f6f667cfSStefano Zampini       S = Sarray + cumarray;
227f6f667cfSStefano Zampini       St = Starray + cumarray;
2288bec7fa6SStefano Zampini     }
22908122e43SStefano Zampini 
230f6f667cfSStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
231aff50787SStefano Zampini     /* see if we can save some work */
232aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
233aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
234aff50787SStefano Zampini     }
235aff50787SStefano Zampini 
236aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
237aff50787SStefano Zampini       B_neigs = 0;
238aff50787SStefano Zampini     } else {
239aff50787SStefano Zampini       /* Threshold: this is an heuristic for edges */
240f6f667cfSStefano Zampini       thresh = pcbddc->mat_graph->count[idxs[0]]*pcbddc->adaptive_threshold;
241f6f667cfSStefano Zampini 
2429ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
24308122e43SStefano Zampini         PetscBLASInt B_itype = 1;
244f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
2454c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
2469552c7c7SStefano Zampini         PetscInt     nmin_s;
24708122e43SStefano Zampini 
248f6f667cfSStefano Zampini         /* ask for eigenvalues larger than thresh */
249fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2508bec7fa6SStefano 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]]);
251fd14bc51SStefano Zampini         }
25208122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
25308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
254f6f667cfSStefano 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));
25508122e43SStefano Zampini #else
256f6f667cfSStefano 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));
25708122e43SStefano Zampini #endif
25808122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
25908122e43SStefano Zampini         if (B_ierr) {
26008122e43SStefano Zampini           if (B_ierr < 0 ) {
26108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
26208122e43SStefano Zampini           } else if (B_ierr <= B_N) {
26308122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
26408122e43SStefano Zampini           } else {
2659552c7c7SStefano 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);
26608122e43SStefano Zampini           }
26708122e43SStefano Zampini         }
26808122e43SStefano Zampini 
26908122e43SStefano Zampini         if (B_neigs > nmax) {
270fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
271fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
272fd14bc51SStefano Zampini           }
273f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
27408122e43SStefano Zampini           B_neigs = nmax;
27508122e43SStefano Zampini         }
27608122e43SStefano Zampini 
2779552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
2789552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
27908122e43SStefano Zampini           PetscBLASInt B_neigs2;
28008122e43SStefano Zampini 
281f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
282f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
283fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
284fd14bc51SStefano 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);
285fd14bc51SStefano Zampini           }
2869ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
28708122e43SStefano Zampini             PetscInt j;
28808122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
28908122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
29008122e43SStefano Zampini             }
29108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
29208122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
29308122e43SStefano Zampini             }
29408122e43SStefano Zampini           } else {
29508122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
29608122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
29708122e43SStefano Zampini           }
29808122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
29908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
300f6f667cfSStefano 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));
30108122e43SStefano Zampini #else
302f6f667cfSStefano 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));
30308122e43SStefano Zampini #endif
30408122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
30508122e43SStefano Zampini           B_neigs += B_neigs2;
30608122e43SStefano Zampini         }
30708122e43SStefano Zampini         if (B_ierr) {
30808122e43SStefano Zampini           if (B_ierr < 0 ) {
30908122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
31008122e43SStefano Zampini           } else if (B_ierr <= B_N) {
31108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
31208122e43SStefano Zampini           } else {
3139552c7c7SStefano 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);
31408122e43SStefano Zampini           }
31508122e43SStefano Zampini         }
316fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
317ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
31808122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
31908122e43SStefano Zampini             if (eigs[j] == 0.0) {
320ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
32108122e43SStefano Zampini             } else {
322ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
323fd14bc51SStefano Zampini             }
32408122e43SStefano Zampini           }
32508122e43SStefano Zampini         }
32608122e43SStefano Zampini       } else {
32708122e43SStefano Zampini           /* TODO */
32808122e43SStefano Zampini       }
329aff50787SStefano Zampini     }
3308bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
3318bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
3329162d606SStefano Zampini     if (B_neigs) {
3339162d606SStefano 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);
334fd14bc51SStefano Zampini 
335fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
3369552c7c7SStefano Zampini         PetscInt ii;
3379552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
338ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
3399552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
340ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
341ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
342ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
343ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
344ac47001eSStefano Zampini #else
345ac47001eSStefano 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);
346ac47001eSStefano Zampini #endif
3479552c7c7SStefano Zampini           }
3489552c7c7SStefano Zampini         }
349fd14bc51SStefano Zampini       }
35008122e43SStefano Zampini #if 0
3519162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
35208122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
35308122e43SStefano Zampini         PetscScalar norm;
35408122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
3559162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
3569162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
35708122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
35808122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
35908122e43SStefano Zampini         } else {
36008122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
36108122e43SStefano Zampini         }
3629162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
363b1b3d7a2SStefano Zampini       }
364b1b3d7a2SStefano Zampini #endif
3659162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
3669162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
3679162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
3689162d606SStefano Zampini       cum++;
36908122e43SStefano Zampini     }
37008122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
37108122e43SStefano Zampini     /* shift for next computation */
37208122e43SStefano Zampini     cumarray += subset_size*subset_size;
37308122e43SStefano Zampini   }
374fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
375fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
376fd14bc51SStefano Zampini   }
37708122e43SStefano Zampini 
37808122e43SStefano Zampini   if (mss) {
37908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
38008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
381f6f667cfSStefano Zampini     /* destroy matrices (junk) */
382f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
383f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
38408122e43SStefano Zampini   }
385f6f667cfSStefano Zampini   if (allocated_S_St) {
386f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
387f6f667cfSStefano Zampini   }
388f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
38908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
39008122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
39108122e43SStefano Zampini #endif
39208122e43SStefano Zampini   if (pcbddc->dbg_flag) {
3931b968477SStefano Zampini     PetscInt maxneigs_r;
39408122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3959b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
39608122e43SStefano Zampini   }
39708122e43SStefano Zampini   PetscFunctionReturn(0);
39808122e43SStefano Zampini }
399b1b3d7a2SStefano Zampini 
400674ae819SStefano Zampini #undef __FUNCT__
401c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
402c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
403c8587f34SStefano Zampini {
404c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4058629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
406c8587f34SStefano Zampini   PetscErrorCode ierr;
407c8587f34SStefano Zampini 
408c8587f34SStefano Zampini   PetscFunctionBegin;
409f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
4105e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
411c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
412c8587f34SStefano Zampini 
413684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
4140fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
415684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
416c8587f34SStefano Zampini 
417c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
418b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
419c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
420c8587f34SStefano Zampini   }
421c8587f34SStefano Zampini 
4228629588bSStefano Zampini   /*
4238629588bSStefano Zampini      Setup local correction and local part of coarse basis.
4248629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
4258629588bSStefano Zampini   */
42647f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
4278629588bSStefano Zampini 
4288629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
4298629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
4308629588bSStefano Zampini 
4318629588bSStefano Zampini   /* free */
4328629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
433c8587f34SStefano Zampini   PetscFunctionReturn(0);
434c8587f34SStefano Zampini }
435c8587f34SStefano Zampini 
436c8587f34SStefano Zampini #undef __FUNCT__
437674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
438674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
439674ae819SStefano Zampini {
440674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
441674ae819SStefano Zampini   PetscErrorCode ierr;
442674ae819SStefano Zampini 
443674ae819SStefano Zampini   PetscFunctionBegin;
444674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
445674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
446674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
447674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
448785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
449674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
450f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
451f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
452785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
45363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
45463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
455674ae819SStefano Zampini   PetscFunctionReturn(0);
456674ae819SStefano Zampini }
457674ae819SStefano Zampini 
458674ae819SStefano Zampini #undef __FUNCT__
459674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
460674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
461674ae819SStefano Zampini {
462674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
463674ae819SStefano Zampini   PetscErrorCode ierr;
464674ae819SStefano Zampini 
465674ae819SStefano Zampini   PetscFunctionBegin;
466b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
467674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
468674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
469674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
470b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
471674ae819SStefano Zampini   PetscFunctionReturn(0);
472674ae819SStefano Zampini }
473674ae819SStefano Zampini 
474674ae819SStefano Zampini #undef __FUNCT__
475674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
476674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
477674ae819SStefano Zampini {
478674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
47906656605SStefano Zampini   PetscScalar    *array;
480674ae819SStefano Zampini   PetscErrorCode ierr;
481674ae819SStefano Zampini 
482674ae819SStefano Zampini   PetscFunctionBegin;
483674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
48458da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
48506656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
48606656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
48758da7f69SStefano Zampini   }
488674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
489674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
49015aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
49115aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
492674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
493674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
494674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
49506656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
496674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
497674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
4988ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
499674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
500674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
501674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
502f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
503f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
504f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
505f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
506727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5070e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
508f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
50970cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
5106e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
511f5fd1fbfSStefano Zampini   ierr = ISDestroy(&pcbddc->zerodiag);CHKERRQ(ierr);
51281d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
51381d14e9dSStefano Zampini   ierr = PetscFree2(pcbddc->B0_cols,pcbddc->B0_vals);CHKERRQ(ierr);
514674ae819SStefano Zampini   PetscFunctionReturn(0);
515674ae819SStefano Zampini }
516674ae819SStefano Zampini 
517674ae819SStefano Zampini #undef __FUNCT__
518f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
519f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
5206bfb1811SStefano Zampini {
5216bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
5226bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
5236bfb1811SStefano Zampini   VecType        impVecType;
524e9189074SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
5256bfb1811SStefano Zampini   PetscErrorCode ierr;
5266bfb1811SStefano Zampini 
5276bfb1811SStefano Zampini   PetscFunctionBegin;
528f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
529f4ddd8eeSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
530f4ddd8eeSStefano Zampini   }
531e7b262bdSStefano Zampini   /* get sizes */
532b371cd4fSStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->n_vertices;
533b371cd4fSStefano Zampini   n_R = pcis->n-pcbddc->n_vertices;
5346bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
535e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
536e7b262bdSStefano Zampini   /* R nodes */
537e7b262bdSStefano Zampini   old_size = -1;
538e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
539e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
540e7b262bdSStefano Zampini   }
541e7b262bdSStefano Zampini   if (n_R != old_size) {
542e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
543e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
5446bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
5456bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
5466bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
5476bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
548e7b262bdSStefano Zampini   }
549e7b262bdSStefano Zampini   /* local primal dofs */
550e7b262bdSStefano Zampini   old_size = -1;
551e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
552e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
553e7b262bdSStefano Zampini   }
554e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
555e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
55683b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
557e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
5586bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
559e7b262bdSStefano Zampini   }
560e7b262bdSStefano Zampini   /* local explicit constraints */
561e7b262bdSStefano Zampini   old_size = -1;
562e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
563e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
564e7b262bdSStefano Zampini   }
565e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
566e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
56783b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
56883b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
56983b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
57083b7ccabSStefano Zampini   }
5716bfb1811SStefano Zampini   PetscFunctionReturn(0);
5726bfb1811SStefano Zampini }
5736bfb1811SStefano Zampini 
5746bfb1811SStefano Zampini #undef __FUNCT__
57547f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
57647f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
57788ebb749SStefano Zampini {
57825084f0cSStefano Zampini   PetscErrorCode  ierr;
57925084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
58088ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
58188ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
582d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
58325084f0cSStefano Zampini   /* submatrices of local problem */
58480677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
58506656605SStefano Zampini   /* submatrices of local coarse problem */
58606656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
58725084f0cSStefano Zampini   /* working matrices */
58806656605SStefano Zampini   Mat             C_CR;
58925084f0cSStefano Zampini   /* additional working stuff */
59006656605SStefano Zampini   PC              pc_R;
59106656605SStefano Zampini   Mat             F;
59206656605SStefano Zampini   PetscBool       isLU,isCHOL,isILU;
59306656605SStefano Zampini 
59425084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
59506656605SStefano Zampini   PetscScalar     *work;
59606656605SStefano Zampini   PetscInt        *idx_V_B;
59706656605SStefano Zampini   PetscInt        n,n_vertices,n_constraints;
59806656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
599b9d89cd5SStefano Zampini   PetscBool       unsymmetric_check;
60045a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
60188ebb749SStefano Zampini   MatType         impMatType;
60225084f0cSStefano Zampini   /* some shortcuts to scalars */
60306656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
60488ebb749SStefano Zampini 
60588ebb749SStefano Zampini   PetscFunctionBegin;
606b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
60788ebb749SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
60888ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
609b371cd4fSStefano Zampini   n_B = pcis->n_B;
610b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
61188ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
61288ebb749SStefano Zampini 
61388ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
61488ebb749SStefano Zampini   impMatType = MATSEQDENSE;
61588ebb749SStefano Zampini 
61688ebb749SStefano Zampini   /* vertices in boundary numbering */
617785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
6180e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
61988ebb749SStefano Zampini   if (i != n_vertices) {
62022d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
62188ebb749SStefano Zampini   }
62288ebb749SStefano Zampini 
62306656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
62406656605SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
62506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
62606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
62706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
62806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
62906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
63006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
63106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
63206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
63306656605SStefano Zampini 
63406656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
63506656605SStefano Zampini   /* allocate workspace */
63606656605SStefano Zampini   n = 0;
63706656605SStefano Zampini   if (n_constraints) {
63806656605SStefano Zampini     n += n_R*n_constraints;
63906656605SStefano Zampini   }
64006656605SStefano Zampini   if (n_vertices) {
64106656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
64280677318SStefano Zampini     n = PetscMax((n_R+n_B)*n_vertices,n);
64306656605SStefano Zampini   }
6443301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
64506656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
64606656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
64706656605SStefano Zampini   }
64806656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
64906656605SStefano Zampini 
65006656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
65106656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
65206656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
65306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
65406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
65506656605SStefano Zampini   if (isLU || isILU || isCHOL) {
65606656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
657d62866d3SStefano Zampini   } else if (sub_schurs->reuse_mumps) {
658d62866d3SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
659d62866d3SStefano Zampini     MatFactorType type;
660d62866d3SStefano Zampini 
6616816873aSStefano Zampini     F = reuse_mumps->F;
6626816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
663d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
66406656605SStefano Zampini   } else {
66506656605SStefano Zampini     F = NULL;
66606656605SStefano Zampini   }
66706656605SStefano Zampini 
66888ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
66988ebb749SStefano Zampini   if (n_constraints) {
67006656605SStefano Zampini     Mat         M1,M2,M3;
67180677318SStefano Zampini     Mat         auxmat;
67206656605SStefano Zampini     IS          is_aux;
67380677318SStefano Zampini     PetscScalar *array,*array2;
67406656605SStefano Zampini 
675f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
67680677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
67788ebb749SStefano Zampini 
67825084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
67925084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
6808ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
68180677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
68288ebb749SStefano Zampini 
68380677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
68480677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
68506656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
68688ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
68706656605SStefano Zampini       const PetscScalar *row_cmat_values;
68806656605SStefano Zampini       const PetscInt    *row_cmat_indices;
68906656605SStefano Zampini       PetscInt          size_of_constraint,j;
69088ebb749SStefano Zampini 
69106656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
69206656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
69306656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
69406656605SStefano Zampini       }
69506656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
69606656605SStefano Zampini     }
69780677318SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
69806656605SStefano Zampini     if (F) {
69906656605SStefano Zampini       Mat B;
70006656605SStefano Zampini 
70106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
70280677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
70306656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
70406656605SStefano Zampini     } else {
70580677318SStefano Zampini       PetscScalar *marr;
70680677318SStefano Zampini 
70780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
70806656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
70906656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
71080677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*n_R);CHKERRQ(ierr);
71106656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
71206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
71306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
71406656605SStefano Zampini       }
71580677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
71606656605SStefano Zampini     }
71780677318SStefano Zampini     if (!pcbddc->switch_static) {
71880677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
71980677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
72080677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
72180677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
72280677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*n_R);CHKERRQ(ierr);
72380677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
72480677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
72580677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
72680677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
72780677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
72880677318SStefano Zampini       }
72980677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
73080677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
73180677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
73280677318SStefano Zampini     } else {
73380677318SStefano Zampini       ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
73480677318SStefano Zampini       pcbddc->local_auxmat2 = local_auxmat2_R;
73525084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
73680677318SStefano Zampini     }
73780677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
73880677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
73980677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
74006656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
74106656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
74280677318SStefano Zampini     if (isCHOL) {
74380677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
74480677318SStefano Zampini     } else {
74525084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
74680677318SStefano Zampini     }
74780677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
74806656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
74925084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
75025084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
75125084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
75280677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
75380677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
75480677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
75506656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
75606656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
757f4ddd8eeSStefano Zampini   }
75888ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
75988ebb749SStefano Zampini   if (n_vertices) {
76006656605SStefano Zampini     IS is_aux;
7613a50541eSStefano Zampini 
7626816873aSStefano Zampini     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
7636816873aSStefano Zampini       IS tis;
7646816873aSStefano Zampini 
7656816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
7666816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
7676816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
7686816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
7696816873aSStefano Zampini     } else {
7703a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
7716816873aSStefano Zampini     }
7729577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
7739577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
77404708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
77525084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
77688ebb749SStefano Zampini   }
77788ebb749SStefano Zampini 
77888ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
779f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
78006656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
78106656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
78206656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
78306656605SStefano Zampini     }
784f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
78506656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
78606656605SStefano Zampini       PetscScalar *marray;
78706656605SStefano Zampini 
78806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
78906656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
790f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
791f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
792f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
793f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
794f4ddd8eeSStefano Zampini     }
795f4ddd8eeSStefano Zampini   }
79606656605SStefano Zampini 
797f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
79806656605SStefano Zampini     PetscScalar *marray;
79988ebb749SStefano Zampini 
80006656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
8018eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
80206656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
80388ebb749SStefano Zampini     }
8043301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
80506656605SStefano Zampini       n *= 2;
80688ebb749SStefano Zampini     }
80706656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
80806656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
80906656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
8108eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
81106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
81206656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
81388ebb749SStefano Zampini     }
8143301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
81506656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
8168eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
81706656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
81806656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
81988ebb749SStefano Zampini       }
82088ebb749SStefano Zampini     } else {
821c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
822c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
8231b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
824c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
825c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
826c0553b1fSStefano Zampini       }
82788ebb749SStefano Zampini     }
82806656605SStefano Zampini   }
82906656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
83006656605SStefano Zampini   /* vertices */
83106656605SStefano Zampini   if (n_vertices) {
83216f15bc4SStefano Zampini 
83304708bb6SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
83404708bb6SStefano Zampini 
83516f15bc4SStefano Zampini     if (n_R) {
83606656605SStefano Zampini       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
83706656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
83816f15bc4SStefano Zampini       PetscScalar  *x,*y;
83904708bb6SStefano Zampini       PetscBool    isseqaij;
84006656605SStefano Zampini 
84121eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
84206656605SStefano Zampini       ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
84304708bb6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
8446816873aSStefano Zampini       if (F) { /* TODO could be optimized for symmetric problems */
84506656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
84606656605SStefano Zampini       } else {
84706656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
84806656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
84906656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
85006656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
85106656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
85206656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
85306656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
85406656605SStefano Zampini         }
85506656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
85606656605SStefano Zampini       }
85780677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
85806656605SStefano Zampini       /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
85906656605SStefano Zampini       if (n_constraints) {
86006656605SStefano Zampini         Mat B;
86180677318SStefano Zampini 
862b3d85658SStefano Zampini         ierr = PetscMemzero(work+n_R*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
86380677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
86480677318SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
86580677318SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+n_R*n_vertices+i*n_B);CHKERRQ(ierr);
86680677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
86780677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
86880677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
86980677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
87080677318SStefano Zampini         }
87180677318SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
87280677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
87380677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
87406656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
87580677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
87606656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
87706656605SStefano Zampini         ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
87806656605SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
87906656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
88006656605SStefano Zampini       }
88104708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
88204708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
88304708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
88404708bb6SStefano Zampini       }
88506656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
88680677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
88706656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
88806656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
88906656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
89006656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
89106656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
89206656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
89306656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
89406656605SStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
89516f15bc4SStefano Zampini     } else {
89616f15bc4SStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
89716f15bc4SStefano Zampini     }
89821eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
89906656605SStefano Zampini     /* coarse basis functions */
90006656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
90116f15bc4SStefano Zampini       PetscScalar *y;
90216f15bc4SStefano Zampini 
90306656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
90406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
90506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
90606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
90706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
90806656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
90906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
91006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
91106656605SStefano Zampini 
91206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
91306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
91406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
91506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
91606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
91706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
91806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
91906656605SStefano Zampini       }
92006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
92106656605SStefano Zampini     }
92204708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
92304708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
92406656605SStefano Zampini   }
92506656605SStefano Zampini 
92606656605SStefano Zampini   if (n_constraints) {
92706656605SStefano Zampini     Mat B;
92806656605SStefano Zampini 
92906656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
93006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
93180677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
93206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
93306656605SStefano Zampini     if (n_vertices) {
93480677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
93580677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
93680677318SStefano Zampini       } else {
93780677318SStefano Zampini         Mat S_VCt;
93880677318SStefano Zampini 
93980677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
94080677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
94180677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
94280677318SStefano Zampini       }
94306656605SStefano Zampini     }
94406656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
94506656605SStefano Zampini     /* coarse basis functions */
94606656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
94706656605SStefano Zampini       PetscScalar *y;
94806656605SStefano Zampini 
94906656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
95006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
95106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
95206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
95306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
95406656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
95506656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
95606656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
95706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
95806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
95906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
96006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
96106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
96206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
96306656605SStefano Zampini       }
96406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
96506656605SStefano Zampini     }
96606656605SStefano Zampini   }
96780677318SStefano Zampini   if (n_constraints) {
96880677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
96980677318SStefano Zampini   }
97006656605SStefano Zampini 
97106656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
9723301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
97306656605SStefano Zampini 
97406656605SStefano Zampini     if (n_constraints) {
97516f15bc4SStefano Zampini       Mat S_CCT,B_C;
97606656605SStefano Zampini 
97780677318SStefano Zampini       /* this is a lazy thing */
97880677318SStefano Zampini       ierr = MatConvert(C_CR,impMatType,MAT_REUSE_MATRIX,&C_CR);CHKERRQ(ierr);
97906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
98006656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
98106656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
98216f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
98306656605SStefano Zampini       if (n_vertices) {
98416f15bc4SStefano Zampini         Mat B_V,S_VCT;
98506656605SStefano Zampini 
98606656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
98706656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
98806656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
98906656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
99016f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
99106656605SStefano Zampini       }
99206656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
99380677318SStefano Zampini     } else { /* if there are no constraints, reset work */
99480677318SStefano Zampini       ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
99506656605SStefano Zampini     }
99616f15bc4SStefano Zampini     if (n_vertices && n_R) {
99706656605SStefano Zampini       Mat          A_VRT;
99880677318SStefano Zampini       PetscScalar  *marray;
99906656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
100006656605SStefano Zampini 
100180677318SStefano Zampini       ierr = MatTranspose(A_VR,MAT_INITIAL_MATRIX,&A_VRT);CHKERRQ(ierr);
100280677318SStefano Zampini       ierr = MatConvert(A_VRT,impMatType,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
100380677318SStefano Zampini       ierr = MatDenseGetArray(A_VRT,&marray);CHKERRQ(ierr);
100406656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
100580677318SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,marray,&B_one,work,&B_one));
100680677318SStefano Zampini       ierr = MatDenseRestoreArray(A_VRT,&marray);CHKERRQ(ierr);
100716f15bc4SStefano Zampini       ierr = MatDestroy(&A_VRT);CHKERRQ(ierr);
100806656605SStefano Zampini     }
100906656605SStefano Zampini 
101006656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
101106656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
101206656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
101306656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
101406656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
101506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
101606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
101706656605SStefano Zampini       }
101806656605SStefano Zampini     } else {
101906656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
102006656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
102106656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
102206656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
102306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
102406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
102506656605SStefano Zampini       }
102606656605SStefano Zampini     }
102706656605SStefano Zampini     /* coarse basis functions */
102806656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
102906656605SStefano Zampini       PetscScalar *y;
103006656605SStefano Zampini 
103106656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
103206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
103306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
103406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
103506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
103606656605SStefano Zampini       if (i<n_vertices) {
103706656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
103806656605SStefano Zampini       }
103906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
104006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
104106656605SStefano Zampini 
104206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
104306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
104406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
104506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
104606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
104706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
104806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
104906656605SStefano Zampini       }
105006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
105106656605SStefano Zampini     }
105206656605SStefano Zampini   }
1053d62866d3SStefano Zampini   /* free memory */
105488ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
105506656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
105606656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
105706656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
105806656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
1059d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
1060d62866d3SStefano Zampini   if (n_vertices) {
1061d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1062d62866d3SStefano Zampini   }
1063d62866d3SStefano Zampini   if (n_constraints) {
1064d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1065d62866d3SStefano Zampini   }
106688ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
106788ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
106888ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
106925084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
107088ebb749SStefano Zampini     Mat         coarse_sub_mat;
107125084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
107288ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
107388ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
107488ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
10758bec7fa6SStefano Zampini     Mat         C_B,CPHI;
10768bec7fa6SStefano Zampini     IS          is_dummy;
10778bec7fa6SStefano Zampini     Vec         mones;
107888ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
107988ebb749SStefano Zampini     PetscReal   real_value;
108088ebb749SStefano Zampini 
108188ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
108288ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
108388ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
108488ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
108588ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
108688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1087c0553b1fSStefano Zampini     if (unsymmetric_check) {
108888ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
108988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
109088ebb749SStefano Zampini     }
109188ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
109288ebb749SStefano Zampini 
109325084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
10943301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
109525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1096c0553b1fSStefano Zampini     if (unsymmetric_check) {
109788ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
109888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
109988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
110088ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
110188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
110288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
110388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
110488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
110588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
110688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
110788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
110888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
110988ebb749SStefano Zampini     } else {
111088ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
111188ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
111288ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
111388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
111488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
111588ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
111688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
111788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
111888ebb749SStefano Zampini     }
111988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
112088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
112188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
112288ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
112381d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
11248bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
11250fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
112606656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
11278bec7fa6SStefano Zampini 
11288bec7fa6SStefano Zampini     /* check constraints */
11298bec7fa6SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
11308bec7fa6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
11318bec7fa6SStefano Zampini     ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
11328bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
11338bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
11348bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
11358bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1136bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1137c0553b1fSStefano Zampini     if (unsymmetric_check) {
1138bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1139bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1140bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1141bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1142bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
114388ebb749SStefano Zampini     }
11448bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
11458bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
11468bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
11478bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
11488bec7fa6SStefano Zampini 
114925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
115088ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
115188ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
115288ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
115388ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
115488ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
115588ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
115688ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
115788ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
115888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
115988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1160c0553b1fSStefano Zampini     if (unsymmetric_check) {
116188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
116288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
116388ebb749SStefano Zampini     }
116488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
116588ebb749SStefano Zampini   }
11668629588bSStefano Zampini   /* get back data */
11678629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
116888ebb749SStefano Zampini   PetscFunctionReturn(0);
116988ebb749SStefano Zampini }
117088ebb749SStefano Zampini 
117188ebb749SStefano Zampini #undef __FUNCT__
1172d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1173d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
1174aa0d41d4SStefano Zampini {
1175d65f70fdSStefano Zampini   Mat            *work_mat;
1176d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1177d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1178d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1179aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1180aa0d41d4SStefano Zampini 
1181aa0d41d4SStefano Zampini   PetscFunctionBegin;
1182d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1183d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1184d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1185d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1186aa0d41d4SStefano Zampini 
1187d65f70fdSStefano Zampini   if (!rsorted) {
1188906d46d4SStefano Zampini     const PetscInt *idxs;
1189906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
1190aa0d41d4SStefano Zampini 
1191d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1192d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1193d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1194d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1195aa0d41d4SStefano Zampini     }
1196d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1197d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1198d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1199d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1200aa0d41d4SStefano Zampini     }
1201d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1202d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1203d65f70fdSStefano Zampini   } else {
1204d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1205d65f70fdSStefano Zampini     isrow_s = isrow;
1206aa0d41d4SStefano Zampini   }
1207906d46d4SStefano Zampini 
1208d65f70fdSStefano Zampini   if (!csorted) {
1209d65f70fdSStefano Zampini     if (isrow == iscol) {
1210d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1211d65f70fdSStefano Zampini       iscol_s = isrow_s;
1212d65f70fdSStefano Zampini     } else {
1213d65f70fdSStefano Zampini       const PetscInt *idxs;
1214d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1215906d46d4SStefano Zampini 
1216d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1217d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1218d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1219d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1220d65f70fdSStefano Zampini       }
1221d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1222d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1223d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1224d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1225d65f70fdSStefano Zampini       }
1226d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1227d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1228d65f70fdSStefano Zampini     }
1229d65f70fdSStefano Zampini   } else {
1230d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1231d65f70fdSStefano Zampini     iscol_s = iscol;
1232d65f70fdSStefano Zampini   }
1233d65f70fdSStefano Zampini 
1234d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1235d65f70fdSStefano Zampini 
1236d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1237906d46d4SStefano Zampini     Mat      new_mat;
1238d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1239906d46d4SStefano Zampini 
1240d65f70fdSStefano Zampini     if (!rsorted) {
1241d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1242d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1243d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1244d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1245906d46d4SStefano Zampini       }
1246d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1247d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1248d65f70fdSStefano Zampini     } else {
1249d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1250906d46d4SStefano Zampini     }
1251d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1252d65f70fdSStefano Zampini 
1253d65f70fdSStefano Zampini     if (!csorted) {
1254d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1255d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1256d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1257d65f70fdSStefano Zampini       } else {
1258d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1259d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1260d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1261d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1262d65f70fdSStefano Zampini         }
1263d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1264d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1265d65f70fdSStefano Zampini       }
1266d65f70fdSStefano Zampini     } else {
1267d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1268d65f70fdSStefano Zampini     }
1269d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1270d65f70fdSStefano Zampini 
1271d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1272d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1273d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1274d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1275d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1276d65f70fdSStefano Zampini   }
1277d65f70fdSStefano Zampini 
1278d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1279d65f70fdSStefano Zampini   *B = work_mat[0];
1280d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1281d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1282d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1283d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1284d65f70fdSStefano Zampini }
1285d65f70fdSStefano Zampini 
1286d65f70fdSStefano Zampini #undef __FUNCT__
12875e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
12885e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1289aa0d41d4SStefano Zampini {
1290aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
12913bbff08aSStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
12925e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1293d65f70fdSStefano Zampini   Mat            new_mat;
12945e8657edSStefano Zampini   IS             is_local,is_global;
1295d65f70fdSStefano Zampini   PetscInt       local_size;
1296d65f70fdSStefano Zampini   PetscBool      isseqaij;
1297aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1298aa0d41d4SStefano Zampini 
1299aa0d41d4SStefano Zampini   PetscFunctionBegin;
1300aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
13015e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
13025e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
13033bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,is_local,&is_global);CHKERRQ(ierr);
1304aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1305d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
1306aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1307906d46d4SStefano Zampini 
1308906d46d4SStefano Zampini   /* check */
1309906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
1310906d46d4SStefano Zampini     Vec       x,x_change;
1311906d46d4SStefano Zampini     PetscReal error;
1312906d46d4SStefano Zampini 
13135e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1314906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
13155e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
1316e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1317e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1318d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
1319e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1320e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1321906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1322906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1323906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1324906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1325906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
1326906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1327906d46d4SStefano Zampini   }
1328906d46d4SStefano Zampini 
132922d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
13309b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
133122d5777bSStefano Zampini   if (isseqaij) {
1332d65f70fdSStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1333aa0d41d4SStefano Zampini   } else {
1334aa0d41d4SStefano Zampini     Mat work_mat;
1335aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1336d65f70fdSStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1337aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
1338aa0d41d4SStefano Zampini   }
13393301b35fSStefano Zampini   if (matis->A->symmetric_set) {
13403301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
1341e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
13423301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
1343e496cd5dSStefano Zampini #endif
13443301b35fSStefano Zampini   }
134545a1bb75SStefano Zampini   /*
134645a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1347d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
134845a1bb75SStefano Zampini   */
1349d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
1350aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
1351aa0d41d4SStefano Zampini }
1352aa0d41d4SStefano Zampini 
1353aa0d41d4SStefano Zampini #undef __FUNCT__
1354a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
13558ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
1356a64d13efSStefano Zampini {
1357a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
1358a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1359d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
136053892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
13613a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
13623a50541eSStefano Zampini   PetscInt        vbs,bs;
13636816873aSStefano Zampini   PetscBT         bitmask=NULL;
1364a64d13efSStefano Zampini   PetscErrorCode  ierr;
1365a64d13efSStefano Zampini 
1366a64d13efSStefano Zampini   PetscFunctionBegin;
1367b23d619eSStefano Zampini   /*
1368b23d619eSStefano Zampini     No need to setup local scatters if
1369b23d619eSStefano Zampini       - primal space is unchanged
1370b23d619eSStefano Zampini         AND
1371b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
1372b23d619eSStefano Zampini         AND
1373b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
1374b23d619eSStefano Zampini   */
1375b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
1376f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
1377f4ddd8eeSStefano Zampini   }
1378f4ddd8eeSStefano Zampini   /* destroy old objects */
1379f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1380f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1381f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1382a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
1383b371cd4fSStefano Zampini   n_B = pcis->n_B;
1384b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
1385b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
13863a50541eSStefano Zampini 
1387a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
13886816873aSStefano Zampini 
138953892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
13906816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
1391854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
1392a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
1393a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
13940e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
1395a64d13efSStefano Zampini     }
1396a64d13efSStefano Zampini 
1397a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
13984641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
13996816873aSStefano Zampini         idx_R_local[n_R++] = i;
1400a64d13efSStefano Zampini       }
1401a64d13efSStefano Zampini     }
140253892102SStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
14036816873aSStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
14046816873aSStefano Zampini 
140553892102SStefano Zampini     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
140653892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
14076816873aSStefano Zampini   }
14083a50541eSStefano Zampini 
14093a50541eSStefano Zampini   /* Block code */
14103a50541eSStefano Zampini   vbs = 1;
14113a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
14123a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
14133a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
14143a50541eSStefano Zampini     PetscInt  *vary;
1415d3df7717SStefano Zampini     if (!sub_schurs->reuse_mumps) {
1416785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
14173a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
1418d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
1419d3df7717SStefano 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 */
14200e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
1421d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
14223a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
14233a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
14243a50541eSStefano Zampini           break;
14253a50541eSStefano Zampini         }
14263a50541eSStefano Zampini       }
1427d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
1428d3df7717SStefano Zampini     } else {
1429d3df7717SStefano Zampini       /* Verify directly the R set */
1430d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
1431d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
1432d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
1433d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
1434d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
1435d3df7717SStefano Zampini             break;
1436d3df7717SStefano Zampini           }
1437d3df7717SStefano Zampini         }
1438d3df7717SStefano Zampini       }
1439d3df7717SStefano Zampini     }
14403a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
14413a50541eSStefano Zampini       vbs = bs;
14423a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
14433a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
14443a50541eSStefano Zampini       }
14453a50541eSStefano Zampini     }
14463a50541eSStefano Zampini   }
14473a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
144853892102SStefano Zampini   if (sub_schurs->reuse_mumps) {
144953892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
145053892102SStefano Zampini 
145153892102SStefano Zampini     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
145253892102SStefano Zampini     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
145353892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
145453892102SStefano Zampini     reuse_mumps->is_R = pcbddc->is_R_local;
145553892102SStefano Zampini   } else {
14563a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
145753892102SStefano Zampini   }
1458a64d13efSStefano Zampini 
1459a64d13efSStefano Zampini   /* print some info if requested */
1460a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
1461a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1462a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
14630fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1464a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1465a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
14663a50541eSStefano 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,pcbddc->local_primal_size);CHKERRQ(ierr);
1467a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1468a64d13efSStefano Zampini   }
1469a64d13efSStefano Zampini 
1470a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
14716816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
14726816873aSStefano Zampini     IS       is_aux1,is_aux2;
14736816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
14746816873aSStefano Zampini 
14753a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1476854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
1477854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
1478a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14794641a718SStefano Zampini     for (i=0; i<n_D; i++) {
14804641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
14814641a718SStefano Zampini     }
1482a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1483a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
14844641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
14854641a718SStefano Zampini         aux_array1[j++] = i;
1486a64d13efSStefano Zampini       }
1487a64d13efSStefano Zampini     }
1488a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1489a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1490a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
14914641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
14924641a718SStefano Zampini         aux_array2[j++] = i;
1493a64d13efSStefano Zampini       }
1494a64d13efSStefano Zampini     }
1495a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1496a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
1497a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1498a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1499a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1500a64d13efSStefano Zampini 
15018eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
1502785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
1503a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
15044641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
15054641a718SStefano Zampini           aux_array1[j++] = i;
1506a64d13efSStefano Zampini         }
1507a64d13efSStefano Zampini       }
1508a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1509a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1510a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1511a64d13efSStefano Zampini     }
15124641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
15133a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1514d62866d3SStefano Zampini   } else {
151553892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
15166816873aSStefano Zampini     IS               tis;
15176816873aSStefano Zampini     PetscInt         schur_size;
15186816873aSStefano Zampini 
151953892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
15206816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
152153892102SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
15226816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
15236816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
15246816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
15256816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
15266816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
1527d62866d3SStefano Zampini     }
1528d62866d3SStefano Zampini   }
1529a64d13efSStefano Zampini   PetscFunctionReturn(0);
1530a64d13efSStefano Zampini }
1531a64d13efSStefano Zampini 
1532304d26faSStefano Zampini 
1533304d26faSStefano Zampini #undef __FUNCT__
1534304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1535684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1536304d26faSStefano Zampini {
1537304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1538304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1539304d26faSStefano Zampini   PC             pc_temp;
1540304d26faSStefano Zampini   Mat            A_RR;
1541f4ddd8eeSStefano Zampini   MatReuse       reuse;
1542304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1543304d26faSStefano Zampini   PetscReal      value;
154404708bb6SStefano Zampini   PetscInt       n_D,n_R;
15459577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1546304d26faSStefano Zampini   PetscErrorCode ierr;
1547e604994aSStefano Zampini   /* prefixes stuff */
1548312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1549e604994aSStefano Zampini   size_t         len;
1550304d26faSStefano Zampini 
1551304d26faSStefano Zampini   PetscFunctionBegin;
1552304d26faSStefano Zampini 
1553e604994aSStefano Zampini   /* compute prefixes */
1554e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1555e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1556e604994aSStefano Zampini   if (!pcbddc->current_level) {
1557e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1558e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1559e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1560e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1561e604994aSStefano Zampini   } else {
1562e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1563312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1564e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1565e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1566312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1567312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
156834d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
156934d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1570e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1571e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1572e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1573e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1574e604994aSStefano Zampini   }
1575e604994aSStefano Zampini 
1576304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1577684f6988SStefano Zampini   if (dirichlet) {
1578d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
15793301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
15803301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
1581964fefecSStefano Zampini     }
1582ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
1583964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
1584304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1585304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1586304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1587304d26faSStefano Zampini       /* default */
1588304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1589e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
15909577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1591304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
15929577ea80SStefano Zampini       if (issbaij) {
15939577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
15949577ea80SStefano Zampini       } else {
1595304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
15969577ea80SStefano Zampini       }
1597304d26faSStefano Zampini       /* Allow user's customization */
1598304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1599304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1600304d26faSStefano Zampini     }
1601d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1602d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
1603d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1604d62866d3SStefano Zampini 
1605d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
1606d5574798SStefano Zampini     }
1607304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1608304d26faSStefano Zampini     if (!n_D) {
1609304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1610304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1611304d26faSStefano Zampini     }
1612304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1613304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1614304d26faSStefano Zampini     /* set ksp_D into pcis data */
1615304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1616304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1617304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1618684f6988SStefano Zampini   }
1619304d26faSStefano Zampini 
1620304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1621684f6988SStefano Zampini   A_RR = 0;
1622684f6988SStefano Zampini   if (neumann) {
1623d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
162404708bb6SStefano Zampini     PetscInt        ibs,mbs;
162504708bb6SStefano Zampini     PetscBool       issbaij;
162604708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
1627f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
16288ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1629f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1630f4ddd8eeSStefano Zampini       PetscInt nn_R;
163181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1632f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1633f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1634f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1635f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1636f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1637f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1638f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1639727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1640f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1641f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1642f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1643f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1644f4ddd8eeSStefano Zampini         }
1645f4ddd8eeSStefano Zampini       }
1646f4ddd8eeSStefano Zampini       /* last check */
1647d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1648f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1649f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1650f4ddd8eeSStefano Zampini       }
1651f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1652f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1653f4ddd8eeSStefano Zampini     }
1654f4ddd8eeSStefano Zampini     /* extract A_RR */
1655af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1656af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
165704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
165804708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
165904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
166004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
166104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
1662af732b37SStefano Zampini       } else {
166304708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
16646816873aSStefano Zampini       }
166504708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
166604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
166704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
166804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
166904708bb6SStefano Zampini       } else {
167004708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
167104708bb6SStefano Zampini       }
167204708bb6SStefano Zampini     }
167304708bb6SStefano Zampini     if (!sub_schurs->reuse_mumps) {
1674f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
16753301b35fSStefano Zampini       if (pcbddc->local_mat->symmetric_set) {
16763301b35fSStefano Zampini         ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
16776816873aSStefano Zampini       }
16786816873aSStefano Zampini     } else {
16796816873aSStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
16806816873aSStefano Zampini 
16816816873aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
16826816873aSStefano Zampini       ierr = PCGetOperators(reuse_mumps->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
16836816873aSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1684af732b37SStefano Zampini     }
1685f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
1686304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1687304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1688304d26faSStefano Zampini       /* default */
1689304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1690e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
1691304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
16929577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
16939577ea80SStefano Zampini       if (issbaij) {
16949577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
16959577ea80SStefano Zampini       } else {
1696304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
16979577ea80SStefano Zampini       }
1698304d26faSStefano Zampini       /* Allow user's customization */
1699304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1700304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1701304d26faSStefano Zampini     }
1702d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
1703304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1704304d26faSStefano Zampini     if (!n_R) {
1705304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1706304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1707304d26faSStefano Zampini     }
1708d62866d3SStefano Zampini     /* Reuse MUMPS solver if it is present */
1709d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
1710d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1711d62866d3SStefano Zampini 
1712d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
1713d62866d3SStefano Zampini     }
1714304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
1715304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1716684f6988SStefano Zampini   }
17176816873aSStefano Zampini   /* free Neumann problem's matrix */
17186816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1719304d26faSStefano Zampini 
1720304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
17210fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
1722684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
1723684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1724684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1725684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1726684f6988SStefano Zampini     }
1727684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
17280fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
17290fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
17300fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
17310fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
17320fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
1733304d26faSStefano Zampini       /* need to be adapted? */
1734b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1735b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1736b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
1737304d26faSStefano Zampini       /* print info */
1738304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1739e604994aSStefano 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);
1740304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1741304d26faSStefano Zampini       }
1742b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
1743298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
1744304d26faSStefano Zampini       }
1745684f6988SStefano Zampini     }
1746684f6988SStefano Zampini     if (neumann) { /* Neumann */
17476816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
17480fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
17490fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
17500fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
17510fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
17520fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
1753304d26faSStefano Zampini       /* need to be adapted? */
1754b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1755b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1756304d26faSStefano Zampini       /* print info */
1757304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1758e604994aSStefano 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);
1759304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1760304d26faSStefano Zampini       }
1761b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
1762298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
1763304d26faSStefano Zampini       }
17640fccc4e9SStefano Zampini     }
1765684f6988SStefano Zampini   }
1766304d26faSStefano Zampini   PetscFunctionReturn(0);
1767304d26faSStefano Zampini }
1768304d26faSStefano Zampini 
1769304d26faSStefano Zampini #undef __FUNCT__
1770ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
177180677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
1772674ae819SStefano Zampini {
1773674ae819SStefano Zampini   PetscErrorCode  ierr;
1774674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1775be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
1776674ae819SStefano Zampini 
1777674ae819SStefano Zampini   PetscFunctionBegin;
1778be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
177980677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
178020c7b377SStefano Zampini   }
178180677318SStefano Zampini   if (!pcbddc->switch_static) {
178280677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
178380677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
178480677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
178520c7b377SStefano Zampini     }
1786be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
178780677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
178880677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
178920c7b377SStefano Zampini     } else {
1790be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1791be83ff47SStefano Zampini 
179253892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
179353892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
179420c7b377SStefano Zampini     }
1795be83ff47SStefano Zampini   } else {
179680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
179780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
179880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
179980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
180080677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
180180677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
180280677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
180380677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
180480677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1805674ae819SStefano Zampini     }
1806674ae819SStefano Zampini   }
1807be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
180880677318SStefano Zampini     if (applytranspose) {
180980677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
181080677318SStefano Zampini     } else {
181180677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
181280677318SStefano Zampini     }
181353892102SStefano Zampini #if defined(PETSC_HAVE_MUMPS)
1814be83ff47SStefano Zampini   } else {
1815be83ff47SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1816be83ff47SStefano Zampini 
1817be83ff47SStefano Zampini     if (applytranspose) {
181853892102SStefano Zampini       ierr = MatMumpsSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
1819be83ff47SStefano Zampini     } else {
182053892102SStefano Zampini       ierr = MatMumpsSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
1821be83ff47SStefano Zampini     }
182253892102SStefano Zampini #endif
1823be83ff47SStefano Zampini   }
182480677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
182580677318SStefano Zampini   if (!pcbddc->switch_static) {
1826be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
182780677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
182880677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1829be83ff47SStefano Zampini     } else {
1830be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1831be83ff47SStefano Zampini 
183253892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
183353892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1834be83ff47SStefano Zampini     }
183580677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
183680677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
183780677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
183880677318SStefano Zampini     }
183980677318SStefano Zampini   } else {
184080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184480677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
184580677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
184680677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
184780677318SStefano Zampini     }
184880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1852674ae819SStefano Zampini   }
1853674ae819SStefano Zampini   PetscFunctionReturn(0);
1854674ae819SStefano Zampini }
1855674ae819SStefano Zampini 
1856dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
1857674ae819SStefano Zampini #undef __FUNCT__
1858674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
1859dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
1860674ae819SStefano Zampini {
1861674ae819SStefano Zampini   PetscErrorCode ierr;
1862674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1863674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
1864674ae819SStefano Zampini   const PetscScalar zero = 0.0;
1865674ae819SStefano Zampini 
1866674ae819SStefano Zampini   PetscFunctionBegin;
1867dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
1868dc359a40SStefano Zampini   if (applytranspose) {
1869674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
18708eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
1871dc359a40SStefano Zampini   } else {
1872674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
1873674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
187415aaf578SStefano Zampini   }
187512edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
187612edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
187712edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187912edc857SStefano Zampini 
18809f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
188112edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
188212edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
1883964fefecSStefano Zampini     Vec rhs,sol;
1884964fefecSStefano Zampini 
1885964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
1886964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
188712edc857SStefano Zampini     if (applytranspose) {
1888964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
188912edc857SStefano Zampini     } else {
1890964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
189112edc857SStefano Zampini     }
189212edc857SStefano Zampini   }
1893674ae819SStefano Zampini 
1894674ae819SStefano Zampini   /* Local solution on R nodes */
189580677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
189680677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
18979f00e9b4SStefano Zampini   }
1898674ae819SStefano Zampini 
18999f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
19009f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
190112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1902674ae819SStefano Zampini 
1903674ae819SStefano Zampini   /* Sum contributions from two levels */
1904dc359a40SStefano Zampini   if (applytranspose) {
1905dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
1906dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1907dc359a40SStefano Zampini   } else {
1908674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
19098eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1910dc359a40SStefano Zampini   }
1911674ae819SStefano Zampini   PetscFunctionReturn(0);
1912674ae819SStefano Zampini }
1913674ae819SStefano Zampini 
1914674ae819SStefano Zampini #undef __FUNCT__
1915674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
191612edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
1917674ae819SStefano Zampini {
1918674ae819SStefano Zampini   PetscErrorCode ierr;
1919674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
192058da7f69SStefano Zampini   PetscScalar    *array;
192112edc857SStefano Zampini   Vec            from,to;
1922674ae819SStefano Zampini 
1923674ae819SStefano Zampini   PetscFunctionBegin;
192412edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
192512edc857SStefano Zampini     from = pcbddc->coarse_vec;
192612edc857SStefano Zampini     to = pcbddc->vec1_P;
192712edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
192812edc857SStefano Zampini       Vec tvec;
192958da7f69SStefano Zampini 
193058da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
193158da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
193212edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
193358da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
193458da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
193558da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
193612edc857SStefano Zampini     }
193712edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
193812edc857SStefano Zampini     from = pcbddc->vec1_P;
193912edc857SStefano Zampini     to = pcbddc->coarse_vec;
194012edc857SStefano Zampini   }
194112edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
1942674ae819SStefano Zampini   PetscFunctionReturn(0);
1943674ae819SStefano Zampini }
1944674ae819SStefano Zampini 
1945674ae819SStefano Zampini #undef __FUNCT__
1946674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
194712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
1948674ae819SStefano Zampini {
1949674ae819SStefano Zampini   PetscErrorCode ierr;
1950674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
195158da7f69SStefano Zampini   PetscScalar    *array;
195212edc857SStefano Zampini   Vec            from,to;
1953674ae819SStefano Zampini 
1954674ae819SStefano Zampini   PetscFunctionBegin;
195512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
195612edc857SStefano Zampini     from = pcbddc->coarse_vec;
195712edc857SStefano Zampini     to = pcbddc->vec1_P;
195812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
195912edc857SStefano Zampini     from = pcbddc->vec1_P;
196012edc857SStefano Zampini     to = pcbddc->coarse_vec;
196112edc857SStefano Zampini   }
196212edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
196312edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
196412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
196512edc857SStefano Zampini       Vec tvec;
196658da7f69SStefano Zampini 
196712edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
196858da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
196958da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
197058da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
197158da7f69SStefano Zampini     }
197258da7f69SStefano Zampini   } else {
197358da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
197458da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
197512edc857SStefano Zampini     }
197612edc857SStefano Zampini   }
1977674ae819SStefano Zampini   PetscFunctionReturn(0);
1978674ae819SStefano Zampini }
1979674ae819SStefano Zampini 
1980984c4197SStefano Zampini /* uncomment for testing purposes */
1981984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
1982674ae819SStefano Zampini #undef __FUNCT__
1983674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
1984674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
1985674ae819SStefano Zampini {
1986674ae819SStefano Zampini   PetscErrorCode    ierr;
1987674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
1988674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1989674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
1990984c4197SStefano Zampini   /* one and zero */
1991984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
1992984c4197SStefano Zampini   /* space to store constraints and their local indices */
19939162d606SStefano Zampini   PetscScalar       *constraints_data;
19949162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
19959162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
19969162d606SStefano Zampini   PetscInt          *constraints_n;
1997984c4197SStefano Zampini   /* iterators */
1998b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
1999984c4197SStefano Zampini   /* BLAS integers */
2000e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
2001e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2002c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2003727cdba6SStefano Zampini   /* reuse */
20040e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
20050e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2006984c4197SStefano Zampini   /* change of basis */
2007b3d85658SStefano Zampini   PetscBool         qr_needed;
20089162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
2009984c4197SStefano Zampini   /* auxiliary stuff */
201064efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
20118a0068c3SStefano Zampini   PetscInt          ncc;
2012984c4197SStefano Zampini   /* some quantities */
201345a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2014a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2015984c4197SStefano Zampini 
2016674ae819SStefano Zampini   PetscFunctionBegin;
20178e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
20188e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
20198e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2020088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
2021088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
20220e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
20230e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
20240e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
20250e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
20260e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2027088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2028cf5a6209SStefano Zampini 
2029cf5a6209SStefano Zampini   /* print some info */
2030cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
2031cf5a6209SStefano Zampini     IS       vertices;
2032cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
2033cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2034cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2035cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2036cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2037cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2038cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2039fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2040fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2041cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2042cf5a6209SStefano Zampini   }
2043cf5a6209SStefano Zampini 
2044cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
20459162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
2046cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
2047cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
2048cf5a6209SStefano Zampini     Vec          *localnearnullsp;
2049cf5a6209SStefano Zampini     PetscScalar  *array;
2050cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2051cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
2052674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
2053b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
2054674ae819SStefano Zampini     PetscScalar  *work;
2055674ae819SStefano Zampini     PetscReal    *singular_vals;
2056674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2057674ae819SStefano Zampini     PetscReal    *rwork;
2058674ae819SStefano Zampini #endif
2059674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2060674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
2061674ae819SStefano Zampini #else
2062964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
2063964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
2064674ae819SStefano Zampini #endif
2065674ae819SStefano Zampini 
2066674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
2067d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2068d06fc5fdSStefano Zampini     /* free unneeded index sets */
2069d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
2070d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2071674ae819SStefano Zampini     }
2072d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
2073d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
2074d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2075d06fc5fdSStefano Zampini       }
2076d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2077d06fc5fdSStefano Zampini       n_ISForEdges = 0;
2078d06fc5fdSStefano Zampini     }
2079d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
2080d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
2081d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2082d06fc5fdSStefano Zampini       }
2083d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2084d06fc5fdSStefano Zampini       n_ISForFaces = 0;
2085d06fc5fdSStefano Zampini     }
208670022509SStefano Zampini 
208770022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
208870022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
208970022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
209070022509SStefano Zampini     if (pcbddc->NullSpace) {
209170022509SStefano Zampini       PetscBool tbool[2],gbool[2];
209270022509SStefano Zampini 
209370022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2094b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
2095d06fc5fdSStefano Zampini         if (!ISForEdges) {
2096d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
2097d06fc5fdSStefano Zampini         }
2098b8ffe317SStefano Zampini       }
2099d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
2100d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
2101d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2102d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
2103d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
210498a51de6SStefano Zampini     }
210570022509SStefano Zampini #endif
210608122e43SStefano Zampini 
2107674ae819SStefano Zampini     /* check if near null space is attached to global mat */
2108674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2109674ae819SStefano Zampini     if (nearnullsp) {
2110674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2111f4ddd8eeSStefano Zampini       /* remove any stored info */
2112f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2113f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2114f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
2115f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2116f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
2117473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2118f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
2119f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2120f4ddd8eeSStefano Zampini       }
2121984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
2122984c4197SStefano Zampini       nnsp_size = 0;
2123674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
2124674ae819SStefano Zampini     }
2125984c4197SStefano Zampini     /* get max number of constraints on a single cc */
2126984c4197SStefano Zampini     max_constraints = nnsp_size;
2127984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
2128984c4197SStefano Zampini 
2129674ae819SStefano Zampini     /*
2130674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
21319162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
21329162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
21339162d606SStefano Zampini          There can be multiple constraints per connected component
2134674ae819SStefano Zampini                                                                                                                                                            */
2135674ae819SStefano Zampini     n_vertices = 0;
2136674ae819SStefano Zampini     if (ISForVertices) {
2137674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2138674ae819SStefano Zampini     }
21399162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
21409162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
21419162d606SStefano Zampini 
21429162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
21439162d606SStefano Zampini     total_counts *= max_constraints;
2144674ae819SStefano Zampini     total_counts += n_vertices;
21454641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
21469162d606SStefano Zampini 
2147674ae819SStefano Zampini     total_counts = 0;
2148674ae819SStefano Zampini     max_size_of_constraint = 0;
2149674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
21509162d606SStefano Zampini       IS used_is;
2151674ae819SStefano Zampini       if (i<n_ISForEdges) {
21529162d606SStefano Zampini         used_is = ISForEdges[i];
2153674ae819SStefano Zampini       } else {
21549162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
2155674ae819SStefano Zampini       }
21569162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2157674ae819SStefano Zampini       total_counts += j;
2158674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2159674ae819SStefano Zampini     }
21609162d606SStefano 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);
21619162d606SStefano Zampini 
2162984c4197SStefano Zampini     /* get local part of global near null space vectors */
2163785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2164984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2165984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2166e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2167e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2168984c4197SStefano Zampini     }
2169674ae819SStefano Zampini 
2170242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
2171242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
2172a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2173242a89d7SStefano Zampini 
2174984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2175a773dcb8SStefano Zampini     if (!skip_lapack) {
2176674ae819SStefano Zampini       PetscScalar temp_work;
2177911cabfeSStefano Zampini 
2178674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2179984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2180785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2181785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2182785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2183674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2184785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2185674ae819SStefano Zampini #endif
2186674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2187c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2188c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2189674ae819SStefano Zampini       lwork = -1;
2190674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2191674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2192c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2193674ae819SStefano Zampini #else
2194c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2195674ae819SStefano Zampini #endif
2196674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2197984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2198674ae819SStefano Zampini #else /* on missing GESVD */
2199674ae819SStefano Zampini       /* SVD */
2200674ae819SStefano Zampini       PetscInt max_n,min_n;
2201674ae819SStefano Zampini       max_n = max_size_of_constraint;
2202984c4197SStefano Zampini       min_n = max_constraints;
2203984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
2204674ae819SStefano Zampini         min_n = max_size_of_constraint;
2205984c4197SStefano Zampini         max_n = max_constraints;
2206674ae819SStefano Zampini       }
2207785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2208674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2209785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2210674ae819SStefano Zampini #endif
2211674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2212674ae819SStefano Zampini       lwork = -1;
2213e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2214e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2215b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2216674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2217674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
22189162d606SStefano 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));
2219674ae819SStefano Zampini #else
22209162d606SStefano 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));
2221674ae819SStefano Zampini #endif
2222674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2223984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2224984c4197SStefano Zampini #endif /* on missing GESVD */
2225674ae819SStefano Zampini       /* Allocate optimal workspace */
2226674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2227854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2228674ae819SStefano Zampini     }
2229674ae819SStefano Zampini     /* Now we can loop on constraining sets */
2230674ae819SStefano Zampini     total_counts = 0;
22319162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
22329162d606SStefano Zampini     constraints_data_ptr[0] = 0;
2233674ae819SStefano Zampini     /* vertices */
22349162d606SStefano Zampini     if (n_vertices) {
2235674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
22369162d606SStefano Zampini       if (nnsp_has_cnst) { /* it considers all possible vertices */
22379162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2238674ae819SStefano Zampini         for (i=0;i<n_vertices;i++) {
22399162d606SStefano Zampini           constraints_n[total_counts] = 1;
22409162d606SStefano Zampini           constraints_data[total_counts] = 1.0;
22419162d606SStefano Zampini           constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
22429162d606SStefano Zampini           constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2243674ae819SStefano Zampini           total_counts++;
2244674ae819SStefano Zampini         }
2245674ae819SStefano Zampini       } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
2246984c4197SStefano Zampini         PetscBool used_vertex;
2247674ae819SStefano Zampini         for (i=0;i<n_vertices;i++) {
2248674ae819SStefano Zampini           used_vertex = PETSC_FALSE;
2249674ae819SStefano Zampini           k = 0;
2250674ae819SStefano Zampini           while (!used_vertex && k<nnsp_size) {
2251984c4197SStefano Zampini             ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2252984c4197SStefano Zampini             if (PetscAbsScalar(array[is_indices[i]])>0.0) {
22539162d606SStefano Zampini               constraints_n[total_counts] = 1;
22549162d606SStefano Zampini               constraints_idxs[total_counts] = is_indices[i];
22559162d606SStefano Zampini               constraints_data[total_counts] = 1.0;
22569162d606SStefano Zampini               constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
22579162d606SStefano Zampini               constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2258674ae819SStefano Zampini               total_counts++;
2259674ae819SStefano Zampini               used_vertex = PETSC_TRUE;
2260674ae819SStefano Zampini             }
2261984c4197SStefano Zampini             ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2262674ae819SStefano Zampini             k++;
2263674ae819SStefano Zampini           }
2264674ae819SStefano Zampini         }
2265674ae819SStefano Zampini       }
2266674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2267674ae819SStefano Zampini       n_vertices = total_counts;
2268674ae819SStefano Zampini     }
2269984c4197SStefano Zampini 
2270674ae819SStefano Zampini     /* edges and faces */
22719162d606SStefano Zampini     total_counts_cc = total_counts;
2272911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
22739162d606SStefano Zampini       IS        used_is;
22749162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
22759162d606SStefano Zampini 
2276911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
22779162d606SStefano Zampini         used_is = ISForEdges[ncc];
2278984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2279674ae819SStefano Zampini       } else {
22809162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
2281984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2282674ae819SStefano Zampini       }
2283674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
22849162d606SStefano Zampini 
22859162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
22869162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2287984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
2288984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2289674ae819SStefano Zampini       if (nnsp_has_cnst) {
22905b08dc53SStefano Zampini         PetscScalar quad_value;
22919162d606SStefano Zampini 
22929162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
22939162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
22949162d606SStefano Zampini 
2295a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
2296674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2297a773dcb8SStefano Zampini         } else {
2298a773dcb8SStefano Zampini           quad_value = 1.0;
2299a773dcb8SStefano Zampini         }
2300674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
23019162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
2302674ae819SStefano Zampini         }
23039162d606SStefano Zampini         temp_constraints++;
2304674ae819SStefano Zampini         total_counts++;
2305674ae819SStefano Zampini       }
2306674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
2307984c4197SStefano Zampini         PetscReal real_value;
23089162d606SStefano Zampini         PetscScalar *ptr_to_data;
23099162d606SStefano Zampini 
2310984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
23119162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
2312674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
23139162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
2314674ae819SStefano Zampini         }
2315984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2316984c4197SStefano Zampini         /* check if array is null on the connected component */
2317e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
23189162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
23195b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2320674ae819SStefano Zampini           temp_constraints++;
2321674ae819SStefano Zampini           total_counts++;
23229162d606SStefano Zampini           if (!idxs_copied) {
23239162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
23249162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
2325674ae819SStefano Zampini           }
2326674ae819SStefano Zampini         }
23279162d606SStefano Zampini       }
23289162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
232945a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2330eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2331a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
23329162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
23339162d606SStefano Zampini 
23349162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2335a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
23369162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
2337a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
23389162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
2339a773dcb8SStefano Zampini         } else { /* perform SVD */
2340984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
23419162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2342674ae819SStefano Zampini 
2343674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2344984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
2345984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
2346984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
2347984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
2348984c4197SStefano Zampini                 from that computed using LAPACKgesvd
2349984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
2350984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
2351984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
2352674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
2353e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2354984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2355674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
2356674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
23579162d606SStefano 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));
2358674ae819SStefano Zampini             }
2359674ae819SStefano Zampini           }
2360e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
2361e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2362e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
2363674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2364c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
2365674ae819SStefano Zampini #else
2366c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
2367674ae819SStefano Zampini #endif
2368674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2369984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
2370984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
2371674ae819SStefano Zampini           j = 0;
2372984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
2373674ae819SStefano Zampini           total_counts = total_counts-j;
237445a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
2375e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
2376c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2377c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2378c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
2379c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2380c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
2381c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2382674ae819SStefano Zampini           if (j<temp_constraints) {
2383984c4197SStefano Zampini             PetscInt ii;
2384984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
2385674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
23869162d606SStefano 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));
2387674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2388984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
2389674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
23909162d606SStefano 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];
2391674ae819SStefano Zampini               }
2392674ae819SStefano Zampini             }
2393674ae819SStefano Zampini           }
2394674ae819SStefano Zampini #else  /* on missing GESVD */
2395e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2396e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2397b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2398674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2399674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
24009162d606SStefano 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));
2401674ae819SStefano Zampini #else
24029162d606SStefano 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));
2403674ae819SStefano Zampini #endif
2404984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
2405674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2406984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
2407e310c8b4SStefano Zampini           k = temp_constraints;
2408e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
2409674ae819SStefano Zampini           j = 0;
2410e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
241145a1bb75SStefano Zampini           valid_constraints = k-j;
2412911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
2413984c4197SStefano Zampini #endif /* on missing GESVD */
2414674ae819SStefano Zampini         }
2415a773dcb8SStefano Zampini       }
24169162d606SStefano Zampini       /* update pointers information */
24179162d606SStefano Zampini       if (valid_constraints) {
24189162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
24199162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
24209162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
24219162d606SStefano Zampini         /* set change_of_basis flag */
242245a1bb75SStefano Zampini         if (boolforchange) {
2423b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
24249162d606SStefano Zampini         }
2425b3d85658SStefano Zampini         total_counts_cc++;
242645a1bb75SStefano Zampini       }
242745a1bb75SStefano Zampini     }
2428984c4197SStefano Zampini     /* free workspace */
24298f1c130eSStefano Zampini     if (!skip_lapack) {
2430984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
2431984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2432984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
2433984c4197SStefano Zampini #endif
2434984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
2435984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2436984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
2437984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2438984c4197SStefano Zampini #endif
2439984c4197SStefano Zampini     }
2440984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2441984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
2442984c4197SStefano Zampini     }
2443984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
2444cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
2445cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
2446cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2447cf5a6209SStefano Zampini     }
2448cf5a6209SStefano Zampini     if (n_ISForFaces) {
2449cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2450cf5a6209SStefano Zampini     }
2451cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
2452cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2453cf5a6209SStefano Zampini     }
2454cf5a6209SStefano Zampini     if (n_ISForEdges) {
2455cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2456cf5a6209SStefano Zampini     }
2457cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
245808122e43SStefano Zampini   } else {
245908122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2460984c4197SStefano Zampini 
246108122e43SStefano Zampini     total_counts = 0;
246208122e43SStefano Zampini     n_vertices = 0;
2463d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
2464d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
246508122e43SStefano Zampini     }
246608122e43SStefano Zampini     max_constraints = 0;
24679162d606SStefano Zampini     total_counts_cc = 0;
246808122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
246908122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
24709162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
247108122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
247208122e43SStefano Zampini     }
24739162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
24749162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
24759162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
24769162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
247774d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
24789162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
24799162d606SStefano Zampini     total_counts_cc = 0;
24809162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
24819162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
24829162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
248308122e43SStefano Zampini       }
248408122e43SStefano Zampini     }
24859162d606SStefano Zampini #if 0
24869162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
24879162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
24889162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
24899162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
24909162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
24919162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
24929162d606SStefano Zampini       }
24939162d606SStefano Zampini       printf("\n");
24949162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
24959162d606SStefano Zampini     }
24961b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
24978bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
24981b968477SStefano Zampini     }
24991b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
25008bec7fa6SStefano 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]);
25011b968477SStefano Zampini     }
250208122e43SStefano Zampini #endif
250308122e43SStefano Zampini 
25048bec7fa6SStefano Zampini     max_size_of_constraint = 0;
25059162d606SStefano 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]);
25069162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
250708122e43SStefano Zampini     /* Change of basis */
2508b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
250908122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
251008122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
251108122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
2512b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
251308122e43SStefano Zampini         }
251408122e43SStefano Zampini       }
251508122e43SStefano Zampini     }
251608122e43SStefano Zampini   }
2517984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
25180e6343abSStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
251908122e43SStefano Zampini 
25209162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
25219162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
25229162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
25239162d606SStefano 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);
252408122e43SStefano Zampini   }
2525674ae819SStefano Zampini 
2526674ae819SStefano Zampini   /* Create constraint matrix */
2527674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
252816f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
2529984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
2530984c4197SStefano Zampini 
2531984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
2532a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
2533a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
253474d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
2535984c4197SStefano Zampini   total_primal_vertices=0;
2536b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
25379162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
25389162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2539984c4197SStefano Zampini     if (size_of_constraint == 1) {
25409162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
2541b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
254264efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
25439162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
25449162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
2545a717540cSStefano Zampini       }
2546b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
254774d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
2548a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
2549a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
2550a717540cSStefano Zampini       }
2551fa434743SStefano Zampini     } else {
2552b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
2553fa434743SStefano Zampini     }
2554a717540cSStefano Zampini   }
2555b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
2556b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
2557674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
255870022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2559b3d85658SStefano Zampini 
2560b3d85658SStefano Zampini   ierr = PetscMalloc2(pcbddc->local_primal_size_cc,&pcbddc->local_primal_ref_node,pcbddc->local_primal_size_cc,&pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
25610e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
25620e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
2563984c4197SStefano Zampini 
2564984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
256574d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
2566785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2567984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
256874d5cdf7SStefano Zampini 
2569984c4197SStefano Zampini   j = total_primal_vertices;
257074d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
2571b3d85658SStefano Zampini   cum = total_primal_vertices;
25729162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
25734641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2574b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
2575b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
2576b3d85658SStefano Zampini       cum++;
25779162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
257874d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
257974d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
258074d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
258174d5cdf7SStefano Zampini       }
25829162d606SStefano Zampini       j += constraints_n[i];
2583674ae819SStefano Zampini     }
2584674ae819SStefano Zampini   }
2585674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2586674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2587088faed8SStefano Zampini 
2588674ae819SStefano Zampini   /* set values in constraint matrix */
2589984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
25900e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2591674ae819SStefano Zampini   }
2592984c4197SStefano Zampini   total_counts = total_primal_vertices;
25939162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
25944641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
25959162d606SStefano Zampini       PetscInt *cols;
25969162d606SStefano Zampini 
25979162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
25989162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
25999162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
26009162d606SStefano Zampini         PetscInt    row = total_counts+k;
26019162d606SStefano Zampini         PetscScalar *vals;
26029162d606SStefano Zampini 
26039162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
26049162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
26059162d606SStefano Zampini       }
26069162d606SStefano Zampini       total_counts += constraints_n[i];
2607674ae819SStefano Zampini     }
2608674ae819SStefano Zampini   }
2609674ae819SStefano Zampini   /* assembling */
2610674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2611674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2612088faed8SStefano Zampini 
2613984c4197SStefano Zampini   /*
261445a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2615984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2616984c4197SStefano Zampini   */
2617674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2618674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2619026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2620984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2621984c4197SStefano Zampini     /* working stuff for GEQRF */
262281d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2623984c4197SStefano Zampini     PetscBLASInt lqr_work;
2624984c4197SStefano Zampini     /* working stuff for UNGQR */
2625984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2626984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2627984c4197SStefano Zampini     /* working stuff for TRTRS */
2628984c4197SStefano Zampini     PetscScalar  *trs_rhs;
26293f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2630984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2631984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2632984c4197SStefano Zampini     PetscScalar  *start_vals;
2633984c4197SStefano Zampini     /* working stuff for values insertion */
26344641a718SStefano Zampini     PetscBT      is_primal;
263564efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
2636906d46d4SStefano Zampini     /* matrix sizes */
2637906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2638906d46d4SStefano Zampini     /* temporary change of basis */
2639906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2640cf5a6209SStefano Zampini     /* extra space for debugging */
2641cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
2642984c4197SStefano Zampini 
2643906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2644906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
264516f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2646bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
2647906d46d4SStefano Zampini     /* nonzeros for local mat */
2648bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
2649bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
26509162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
2651a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
26529162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2653a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
26549162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
2655a717540cSStefano Zampini         } else {
26569162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
26579162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
2658a717540cSStefano Zampini         }
2659a717540cSStefano Zampini       }
2660a717540cSStefano Zampini     }
2661906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2662bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2663a717540cSStefano Zampini     /* Set initial identity in the matrix */
2664bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
2665906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2666a717540cSStefano Zampini     }
2667a717540cSStefano Zampini 
2668a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2669a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2670a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2671a717540cSStefano Zampini     }
2672a717540cSStefano Zampini 
2673a717540cSStefano Zampini 
2674a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2675a717540cSStefano Zampini     /*
2676a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2677a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2678a717540cSStefano Zampini 
2679a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2680a717540cSStefano Zampini 
2681a6b551f4SStefano 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)
2682a6b551f4SStefano Zampini 
2683a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2684a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2685a717540cSStefano Zampini             |              ...                        |
2686a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2687a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2688a717540cSStefano Zampini 
2689a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2690a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2691a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2692a6b551f4SStefano Zampini 
2693a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2694a717540cSStefano Zampini     */
2695a717540cSStefano Zampini     if (qr_needed) {
2696984c4197SStefano Zampini       /* space to store Q */
2697854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2698984c4197SStefano Zampini       /* first we issue queries for optimal work */
26993f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
27003f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
27013f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2702984c4197SStefano Zampini       lqr_work = -1;
27033f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2704984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
2705984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
2706785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
2707984c4197SStefano Zampini       lgqr_work = -1;
27083f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
27093f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
27103f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
27113f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
27123f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
27133f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
2714984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
2715984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
2716785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
2717984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
2718785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
2719984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
2720785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
2721a717540cSStefano Zampini       /* allocating workspace for check */
2722a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
2723cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
2724a717540cSStefano Zampini       }
2725a717540cSStefano Zampini     }
2726984c4197SStefano Zampini     /* array to store whether a node is primal or not */
27274641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
2728473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
27290e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
273039e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
273139e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
27324641a718SStefano Zampini     }
273339e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
273439e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
273539e2fb2aSStefano Zampini     }
273639e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
2737984c4197SStefano Zampini 
2738a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
27399162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
27409162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
27414641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
2742984c4197SStefano Zampini         /* get constraint info */
27439162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
2744984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
2745984c4197SStefano Zampini 
2746984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
27479162d606SStefano 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);
2748674ae819SStefano Zampini         }
2749984c4197SStefano Zampini 
2750fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
2751a717540cSStefano Zampini 
2752a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
2753a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
27549162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2755a717540cSStefano Zampini           }
2756984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
27579162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2758984c4197SStefano Zampini 
2759984c4197SStefano Zampini           /* compute QR decomposition of constraints */
27603f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
27613f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
27623f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2763674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27643f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
2765984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
2766674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2767984c4197SStefano Zampini 
2768984c4197SStefano Zampini           /* explictly compute R^-T */
2769984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
2770984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
27713f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
27723f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
27733f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
27743f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
2775984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27763f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
2777984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
2778984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2779984c4197SStefano Zampini 
2780a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
27813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
27823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
27833f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
27843f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2785984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27863f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
2787984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
2788984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2789984c4197SStefano Zampini 
2790984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
2791984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
2792984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
27933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
27943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
27953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
27963f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
27973f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
27983f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2799984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
28009162d606SStefano 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));
2801984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
28029162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2803984c4197SStefano Zampini 
2804984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
28059162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
2806984c4197SStefano Zampini           /* insert cols for primal dofs */
2807984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
2808984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
28099162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
2810906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2811984c4197SStefano Zampini           }
2812984c4197SStefano Zampini           /* insert cols for dual dofs */
2813984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
28149162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
2815984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
28169162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
2817906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2818984c4197SStefano Zampini               j++;
2819674ae819SStefano Zampini             }
2820674ae819SStefano Zampini           }
2821984c4197SStefano Zampini 
2822984c4197SStefano Zampini           /* check change of basis */
2823984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
2824984c4197SStefano Zampini             PetscInt   ii,jj;
2825984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
2826c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
2827c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2828c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
2829c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2830c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
2831c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
2832984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2833cf5a6209SStefano 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));
2834984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2835984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
2836984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
2837cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
2838cf5a6209SStefano 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;
2839674ae819SStefano Zampini               }
2840674ae819SStefano Zampini             }
2841984c4197SStefano Zampini             if (!valid_qr) {
284222d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
2843984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
2844984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
2845cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
2846cf5a6209SStefano 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]));
2847674ae819SStefano Zampini                   }
2848cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
2849cf5a6209SStefano 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]));
2850984c4197SStefano Zampini                   }
2851984c4197SStefano Zampini                 }
2852984c4197SStefano Zampini               }
2853674ae819SStefano Zampini             } else {
285422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
2855674ae819SStefano Zampini             }
2856674ae819SStefano Zampini           }
2857a717540cSStefano Zampini         } else { /* simple transformation block */
2858a717540cSStefano Zampini           PetscInt    row,col;
2859a6b551f4SStefano Zampini           PetscScalar val,norm;
2860a6b551f4SStefano Zampini 
2861a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
28629162d606SStefano 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));
2863a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
28649162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
28659162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
2866bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
28679162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
2868906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
28699162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
2870a717540cSStefano Zampini             } else {
2871a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
28729162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
2873a717540cSStefano Zampini                 if (row != col) {
28749162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
2875a717540cSStefano Zampini                 } else {
28769162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
2877a717540cSStefano Zampini                 }
2878906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
2879a717540cSStefano Zampini               }
2880a717540cSStefano Zampini             }
2881a717540cSStefano Zampini           }
288298a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
288322d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
2884a717540cSStefano Zampini           }
2885674ae819SStefano Zampini         }
2886984c4197SStefano Zampini       } else {
2887984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
28889162d606SStefano 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);
2889674ae819SStefano Zampini         }
2890674ae819SStefano Zampini       }
2891674ae819SStefano Zampini     }
2892a717540cSStefano Zampini 
2893a717540cSStefano Zampini     /* free workspace */
2894a717540cSStefano Zampini     if (qr_needed) {
2895984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
2896cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
2897984c4197SStefano Zampini       }
2898984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
2899984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
2900984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
2901984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
2902984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
2903674ae819SStefano Zampini     }
2904a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
2905906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2906906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2907906d46d4SStefano Zampini 
2908906d46d4SStefano Zampini     /* assembling of global change of variable */
2909bbb9e6c6SStefano Zampini     {
2910bbb9e6c6SStefano Zampini       Mat      tmat;
291116f15bc4SStefano Zampini       PetscInt bs;
291216f15bc4SStefano Zampini 
2913906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2914906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2915bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
2916bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
2917bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2918bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
291916f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
292016f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
2921906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2922bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
2923bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2924bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2925bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2926bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
2927e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2928e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2929bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
2930bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
2931906d46d4SStefano Zampini     }
2932906d46d4SStefano Zampini     /* check */
2933906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
2934906d46d4SStefano Zampini       PetscReal error;
2935906d46d4SStefano Zampini       Vec       x,x_change;
2936906d46d4SStefano Zampini 
2937906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
2938906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
2939906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2940906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
2941e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2942e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2943bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2944e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2945e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2946906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
2947906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2948906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2949906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2950bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
2951906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
2952906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2953906d46d4SStefano Zampini     }
2954b96c3477SStefano Zampini 
2955b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
2956b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
2957b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
2958b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
2959ac632422SStefano Zampini         Mat S_new,tmat;
2960bbb9e6c6SStefano Zampini         IS is_all_N;
2961bbb9e6c6SStefano Zampini 
2962bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
29636816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
2964bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
2965ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
2966b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
2967ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
2968ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
2969ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
2970ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
2971ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
2972b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
2973ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
2974ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
2975ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
2976ac632422SStefano Zampini         }
2977b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2978b96c3477SStefano Zampini       }
2979b96c3477SStefano Zampini     }
2980906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
2981906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
2982b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2983b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
2984b9b85e73SStefano Zampini   }
2985906d46d4SStefano Zampini 
2986906d46d4SStefano Zampini   /* set up change of basis context */
2987906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2988906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
2989906d46d4SStefano Zampini 
2990906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
2991906d46d4SStefano Zampini       PetscInt global_size,local_size;
2992906d46d4SStefano Zampini 
2993906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2994906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2995906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
2996906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2997906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
2998906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
2999906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3000906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3001906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3002906d46d4SStefano Zampini     } else {
3003906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3004906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3005906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3006906d46d4SStefano Zampini     }
3007906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
3008906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3009906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3010906d46d4SStefano Zampini     } else {
3011906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3012906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3013906d46d4SStefano Zampini     }
3014906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3015906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3016906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3017906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3018b9b85e73SStefano Zampini   }
3019a717540cSStefano Zampini 
3020727cdba6SStefano Zampini   /* check if a new primal space has been introduced */
3021727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
3022727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
3023aff50787SStefano 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);
3024c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
30250e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
3026aff50787SStefano 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);
3027727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3028727cdba6SStefano Zampini     }
30290e6343abSStefano Zampini   }
30300e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3031727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3032727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3033727cdba6SStefano Zampini 
3034a717540cSStefano Zampini   /* flush dbg viewer */
3035b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
3036b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3037b8ffe317SStefano Zampini   }
3038a717540cSStefano Zampini 
3039e310c8b4SStefano Zampini   /* free workspace */
3040a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
30414641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
304208122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
30439162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
30449162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
304508122e43SStefano Zampini   } else {
30469162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
30479162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
30489162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
304908122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
305008122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
30519162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
30529162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
305308122e43SStefano Zampini   }
3054674ae819SStefano Zampini   PetscFunctionReturn(0);
3055674ae819SStefano Zampini }
3056674ae819SStefano Zampini 
3057674ae819SStefano Zampini #undef __FUNCT__
3058674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
3059674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3060674ae819SStefano Zampini {
3061674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3062674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
3063674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
30647fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
3065674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
3066674ae819SStefano Zampini 
3067674ae819SStefano Zampini   PetscFunctionBegin;
30688e61c736SStefano Zampini   /* Reset previously computed graph */
30698e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3070674ae819SStefano Zampini   /* Init local Graph struct */
30717fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
30723bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3073674ae819SStefano Zampini 
3074575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
3075575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
3076575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
3077575ad6abSStefano Zampini   }
30789577ea80SStefano Zampini 
3079674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
30804d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
30814d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
30824d379d7bSStefano Zampini     PetscInt  nvtxs;
3083e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
3084674ae819SStefano Zampini 
30854d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
30862fffb893SStefano Zampini 
30872fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
30882fffb893SStefano Zampini       if (flg_row) {
30894d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3090b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
30912fffb893SStefano Zampini       }
30922fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
30939b28b941SStefano 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 */
30944d379d7bSStefano Zampini       IS                     is_dummy;
30954d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
30964d379d7bSStefano Zampini       PetscInt               j,sum;
30974d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
30984d379d7bSStefano Zampini       const PetscInt         *idxs;
30994d379d7bSStefano Zampini       PCBDDCGraph            graph;
31004d379d7bSStefano Zampini       PetscBT                is_on_boundary;
31014d379d7bSStefano Zampini 
31024d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
31034d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
31044d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
31054d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
31067fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
31074d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3108e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3109e496cd5dSStefano Zampini       if (flg_row) {
31104d379d7bSStefano Zampini         graph->xadj = xadj;
31114d379d7bSStefano Zampini         graph->adjncy = adjncy;
3112e496cd5dSStefano Zampini       }
31134d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
31144d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3115e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
31164d379d7bSStefano Zampini 
31174d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
31189b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
31194d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
31204d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
31214d379d7bSStefano Zampini         }
31224d379d7bSStefano Zampini       }
31234d379d7bSStefano Zampini 
3124e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
31254d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
31264d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
31274d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
31284d379d7bSStefano Zampini       }
31294d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
31304d379d7bSStefano Zampini 
3131e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
31324d379d7bSStefano Zampini       sum = 0;
31334d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
31344d379d7bSStefano Zampini         PetscInt sizecc = 0;
31354d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
31364d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
31374d379d7bSStefano Zampini             sizecc++;
31384d379d7bSStefano Zampini           }
31394d379d7bSStefano Zampini         }
31404d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
31414d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
31424d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
31434d379d7bSStefano Zampini           }
31444d379d7bSStefano Zampini         }
31454d379d7bSStefano Zampini         sum += sizecc*sizecc;
31464d379d7bSStefano Zampini       }
31474d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
31484d379d7bSStefano Zampini       sum = 0;
3149e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
31504d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
31514d379d7bSStefano Zampini         cxadj[i] = sum;
31524d379d7bSStefano Zampini         sum += temp;
31534d379d7bSStefano Zampini       }
3154e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
31554d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
31564d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
31574d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
31584d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
31594d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
31604d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
31614d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
31624d379d7bSStefano Zampini                 sizecc++;
31634d379d7bSStefano Zampini               }
31644d379d7bSStefano Zampini             }
31654d379d7bSStefano Zampini           }
31664d379d7bSStefano Zampini         }
31674d379d7bSStefano Zampini       }
31689b28b941SStefano Zampini       if (sum) {
3169e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
31704d379d7bSStefano Zampini       } else {
31714d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
31724d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
31734d379d7bSStefano Zampini       }
31744d379d7bSStefano Zampini       graph->xadj = 0;
31754d379d7bSStefano Zampini       graph->adjncy = 0;
31764d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
31774d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
31784d379d7bSStefano Zampini     }
3179674ae819SStefano Zampini   }
31809b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
31819b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3182674ae819SStefano Zampini   }
3183674ae819SStefano Zampini 
318463602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3185674ae819SStefano Zampini   vertex_size = 1;
318663602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
318763602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
318895ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
318963602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3190e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
319163602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3192674ae819SStefano Zampini       }
319363602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
319463602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
319563602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3196674ae819SStefano Zampini     }
319763602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3198674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
319963602bcaSStefano Zampini   } else {
320063602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
320163602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3202854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
320363602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
320463602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
320563602bcaSStefano Zampini       }
320663602bcaSStefano Zampini     }
3207674ae819SStefano Zampini   }
3208674ae819SStefano Zampini 
3209674ae819SStefano Zampini   /* Setup of Graph */
3210785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3211e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3212785d1243SStefano Zampini   }
3213785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3214e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3215785d1243SStefano Zampini   }
3216302440fdSBarry Smith   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);CHKERRQ(ierr);
3217674ae819SStefano Zampini 
3218674ae819SStefano Zampini   /* Graph's connected components analysis */
3219674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3220674ae819SStefano Zampini 
3221674ae819SStefano Zampini   /* print some info to stdout */
3222674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3223302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3224674ae819SStefano Zampini   }
3225fb180af4SStefano Zampini 
3226fb180af4SStefano Zampini   /* mark topography has done */
3227fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3228674ae819SStefano Zampini   PetscFunctionReturn(0);
3229674ae819SStefano Zampini }
3230674ae819SStefano Zampini 
3231dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3232674ae819SStefano Zampini #undef __FUNCT__
3233674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3234dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3235674ae819SStefano Zampini {
3236dc456d91SStefano Zampini   PetscSF        sf;
3237dc456d91SStefano Zampini   PetscLayout    map;
3238dc456d91SStefano Zampini   const PetscInt *idxs;
3239dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
3240dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
3241dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
3242dc456d91SStefano Zampini   PetscMPIInt    commsize;
3243674ae819SStefano Zampini   PetscBool      first_found;
3244674ae819SStefano Zampini   PetscErrorCode ierr;
3245674ae819SStefano Zampini 
3246674ae819SStefano Zampini   PetscFunctionBegin;
3247dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
3248dc456d91SStefano Zampini   if (subset_mult) {
3249dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
3250dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
3251dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
3252674ae819SStefano Zampini   }
3253dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
3254dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
3255dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
3256dc456d91SStefano Zampini   for (i=0;i<n;i++) {
3257dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
3258dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
3259674ae819SStefano Zampini   }
3260dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
3261dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3262dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
3263dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
3264dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
3265dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
3266dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
3267dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
3268dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
3269dc456d91SStefano Zampini 
3270dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
3271dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
3272dc456d91SStefano Zampini   if (subset_mult) {
3273dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3274dc456d91SStefano Zampini 
3275dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3276dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
3277dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3278674ae819SStefano Zampini   } else {
3279dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
3280674ae819SStefano Zampini   }
3281dc456d91SStefano Zampini   /* local size of new subset */
3282dc456d91SStefano Zampini   n_n = 0;
3283dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
3284dc456d91SStefano Zampini 
3285dc456d91SStefano Zampini   /* global indexes in layout */
3286dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
3287dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
3288dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
3289dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
3290dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
3291dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
3292dc456d91SStefano Zampini 
3293dc456d91SStefano Zampini   /* reduce from leaves to roots */
3294dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
329564a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
329664a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
3297dc456d91SStefano Zampini 
3298dc456d91SStefano Zampini   /* count indexes in local part of layout */
3299674ae819SStefano Zampini   nlocals = 0;
3300674ae819SStefano Zampini   first_index = -1;
3301674ae819SStefano Zampini   first_found = PETSC_FALSE;
3302dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
3303dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
3304674ae819SStefano Zampini       first_found = PETSC_TRUE;
3305674ae819SStefano Zampini       first_index = i;
3306674ae819SStefano Zampini     }
3307dc456d91SStefano Zampini     nlocals += root_data[i];
3308674ae819SStefano Zampini   }
3309dc456d91SStefano Zampini 
3310dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
33115fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
3312dc456d91SStefano Zampini   start = 0;
331364a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
33145fa240b1SStefano Zampini #else
331564a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
33165fa240b1SStefano Zampini   start = start-nlocals;
33175fa240b1SStefano Zampini #endif
33185fa240b1SStefano Zampini 
3319dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
3320dc456d91SStefano Zampini     *N_n = start + nlocals;
3321dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
3322dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3323674ae819SStefano Zampini   }
33245fa240b1SStefano Zampini 
33255fa240b1SStefano Zampini   /* adapt root data with cumulative */
3326674ae819SStefano Zampini   if (first_found) {
3327dc456d91SStefano Zampini     PetscInt old_index;
3328dc456d91SStefano Zampini 
3329dc456d91SStefano Zampini     root_data[first_index] += start;
3330674ae819SStefano Zampini     old_index = first_index;
3331dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
3332dc456d91SStefano Zampini       if (root_data[i]) {
3333dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
3334674ae819SStefano Zampini         old_index = i;
3335674ae819SStefano Zampini       }
3336674ae819SStefano Zampini     }
3337674ae819SStefano Zampini   }
3338dc456d91SStefano Zampini 
3339dc456d91SStefano Zampini   /* from roots to leaves */
3340dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3341dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3342dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
3343dc456d91SStefano Zampini 
3344dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
3345dc456d91SStefano Zampini   if (subset_mult) {
3346dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3347dc456d91SStefano Zampini     PetscInt        cum;
3348dc456d91SStefano Zampini 
3349dc456d91SStefano Zampini     cum = 0;
3350dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3351dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3352dc456d91SStefano Zampini       PetscInt j;
3353dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
3354674ae819SStefano Zampini     }
3355dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3356674ae819SStefano Zampini   } else {
3357dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3358dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
3359674ae819SStefano Zampini     }
3360674ae819SStefano Zampini   }
3361dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
3362dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
3363674ae819SStefano Zampini   PetscFunctionReturn(0);
3364674ae819SStefano Zampini }
33659a7d3425SStefano Zampini 
33669a7d3425SStefano Zampini #undef __FUNCT__
33679a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
33689a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
33699a7d3425SStefano Zampini {
33709a7d3425SStefano Zampini   PetscInt       i,j;
33719a7d3425SStefano Zampini   PetscScalar    *alphas;
33729a7d3425SStefano Zampini   PetscErrorCode ierr;
33739a7d3425SStefano Zampini 
33749a7d3425SStefano Zampini   PetscFunctionBegin;
33759a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
3376785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
33779a7d3425SStefano Zampini   for (i=0;i<n;i++) {
33789a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
33799a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
33809a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
33819a7d3425SStefano Zampini   }
33829a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
33839a7d3425SStefano Zampini   PetscFunctionReturn(0);
33849a7d3425SStefano Zampini }
33859a7d3425SStefano Zampini 
3386e7931f94SStefano Zampini #undef __FUNCT__
338770cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
3388b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
3389e7931f94SStefano Zampini {
339052e5ac9dSStefano Zampini   IS             ranks_send_to;
3391e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
3392e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
339352e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
339452e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
33953837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
33962b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
3397e7931f94SStefano Zampini   PetscSubcomm   subcomm;
339852e5ac9dSStefano Zampini   PetscErrorCode ierr;
3399a57a6d2fSStefano Zampini 
3400e7931f94SStefano Zampini   PetscFunctionBegin;
34012b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
34022b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
34032b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
3404e7931f94SStefano Zampini 
3405e7931f94SStefano Zampini   /* Get info on mapping */
34063bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
34073bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3408e7931f94SStefano Zampini 
3409e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
3410785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
3411e7931f94SStefano Zampini   xadj[0] = 0;
3412e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
3413785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
3414785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
3415e7931f94SStefano Zampini 
34162b510759SStefano Zampini   if (threshold) {
3417d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
34182b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3419d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3420d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3421d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3422d023bfaeSStefano Zampini         xadj_count++;
3423e7931f94SStefano Zampini       }
3424e7931f94SStefano Zampini     }
3425d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3426c8587f34SStefano Zampini   } else {
3427e7931f94SStefano Zampini     if (xadj[1]) {
3428e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3429e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3430c8587f34SStefano Zampini     }
3431e7931f94SStefano Zampini   }
34323bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3433e7931f94SStefano Zampini   if (use_square) {
3434e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3435e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3436e7931f94SStefano Zampini     }
3437e7931f94SStefano Zampini   }
3438e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3439e7931f94SStefano Zampini 
34403837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3441e7931f94SStefano Zampini 
3442e7931f94SStefano Zampini   /*
3443e7931f94SStefano Zampini     Restrict work on active processes only.
3444e7931f94SStefano Zampini   */
3445e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3446e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3447e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
34482b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3449d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3450e7931f94SStefano Zampini   if (color) {
3451e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3452e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3453e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3454c8587f34SStefano Zampini   } else {
345552e5ac9dSStefano Zampini     Mat             subdomain_adj;
345652e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
345752e5ac9dSStefano Zampini     MatPartitioning partitioner;
345852e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
345952e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
3460b0c7d250SStefano Zampini     PetscBool       aggregate;
3461b0c7d250SStefano Zampini 
3462306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
3463785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3464e7931f94SStefano Zampini     prank = rank;
3465306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
34668002ef2cSStefano Zampini     /*
3467e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3468e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3469c8587f34SStefano Zampini     }
34708002ef2cSStefano Zampini     */
3471e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3472e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3473c8587f34SStefano Zampini     }
3474e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3475b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
3476b0c7d250SStefano Zampini     if (aggregate) {
3477b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
3478b0c7d250SStefano Zampini       PetscMPIInt nrank;
3479b0c7d250SStefano Zampini       PetscScalar *vals;
3480b0c7d250SStefano Zampini 
3481b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
3482b0c7d250SStefano Zampini       lrows = 0;
3483b0c7d250SStefano Zampini       if (nrank<redprocs) {
3484b0c7d250SStefano Zampini         lrows = size/redprocs;
3485b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
3486b0c7d250SStefano Zampini       }
34875fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
3488b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
3489b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3490b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3491b0c7d250SStefano Zampini       row = nrank;
3492b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
3493b0c7d250SStefano Zampini       cols = adjncy;
3494b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
3495b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
3496b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
3497b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3498b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
349952e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
350052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
350152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3502b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
3503b0c7d250SStefano Zampini     } else {
3504306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
3505b0c7d250SStefano Zampini     }
350622b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3507e7931f94SStefano Zampini 
3508e7931f94SStefano Zampini     /* Partition */
3509306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
3510e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3511e7931f94SStefano Zampini     if (use_vwgt) {
35123837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3513e7931f94SStefano Zampini       v_wgt[0] = local_size;
3514e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3515c8587f34SStefano Zampini     }
351628143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
351728143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3518e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3519e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
352022b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3521e7931f94SStefano Zampini 
352252e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
352352e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
352452e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
352552e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3526b0c7d250SStefano Zampini     if (!redprocs) {
3527b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
352828143c3dSStefano Zampini     } else {
3529b0c7d250SStefano Zampini       PetscInt    idxs[1];
3530b0c7d250SStefano Zampini       PetscMPIInt tag;
3531b0c7d250SStefano Zampini       MPI_Request *reqs;
3532b0c7d250SStefano Zampini 
3533b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
3534b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
3535b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
3536b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
353728143c3dSStefano Zampini       }
3538b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
3539b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3540b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
3541b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
3542e7931f94SStefano Zampini     }
354352e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3544e7931f94SStefano Zampini     /* clean up */
3545e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
354652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
3547e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3548e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3549e7931f94SStefano Zampini   }
3550e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3551e7931f94SStefano Zampini 
3552e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3553e7931f94SStefano Zampini   i = 1;
3554e7931f94SStefano Zampini   if (color) i=0;
3555e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3556e7931f94SStefano Zampini   /* get back IS */
3557e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3558e7931f94SStefano Zampini   PetscFunctionReturn(0);
3559e7931f94SStefano Zampini }
3560e7931f94SStefano Zampini 
3561e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3562e7931f94SStefano Zampini 
3563e7931f94SStefano Zampini #undef __FUNCT__
3564e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
356553a05cb3SStefano 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[])
3566e7931f94SStefano Zampini {
356770cf5478SStefano Zampini   Mat                    local_mat;
3568e7931f94SStefano Zampini   IS                     is_sends_internal;
35699d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
357028143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
35719d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3572e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3573e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3574e7931f94SStefano Zampini   const PetscInt*        is_indices;
3575e7931f94SStefano Zampini   MatType                new_local_type;
3576e7931f94SStefano Zampini   /* buffers */
3577e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
357828143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
35799d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3580e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3581e7931f94SStefano Zampini   /* MPI */
358228143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
358328143c3dSStefano Zampini   PetscSubcomm           subcomm;
3584e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
358528143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
358628143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
358728143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
358828143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
358928143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3590e7931f94SStefano Zampini   PetscErrorCode         ierr;
3591e7931f94SStefano Zampini 
3592e7931f94SStefano Zampini   PetscFunctionBegin;
359328143c3dSStefano Zampini   /* TODO: add missing checks */
359428143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
359528143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
359628143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
359728143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3598e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
359928143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3600e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3601e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3602e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3603e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3604e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
360528143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
360670cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
360770cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
360828143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
360970cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
361070cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
361170cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
361270cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
361370cf5478SStefano Zampini   }
3614e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3615e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3616e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3617e7931f94SStefano Zampini   if (!is_sends) {
361828143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
3619b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
3620c8587f34SStefano Zampini   } else {
3621e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3622e7931f94SStefano Zampini     is_sends_internal = is_sends;
3623c8587f34SStefano Zampini   }
3624e7931f94SStefano Zampini 
3625e7931f94SStefano Zampini   /* get comm */
3626a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3627e7931f94SStefano Zampini 
3628e7931f94SStefano Zampini   /* compute number of sends */
3629e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3630e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3631e7931f94SStefano Zampini 
3632e7931f94SStefano Zampini   /* compute number of receives */
3633e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3634785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3635e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3636e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3637e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3638e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3639e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3640e7931f94SStefano Zampini 
364128143c3dSStefano Zampini   /* restrict comm if requested */
364228143c3dSStefano Zampini   subcomm = 0;
364328143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
364428143c3dSStefano Zampini   if (restrict_comm) {
3645779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
3646779c1cceSStefano Zampini 
364728143c3dSStefano Zampini     color = 0;
364853a05cb3SStefano Zampini     if (restrict_full) {
364953a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
365053a05cb3SStefano Zampini     } else {
365153a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
365253a05cb3SStefano Zampini     }
365328143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
365428143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
365528143c3dSStefano Zampini     /* check if reuse has been requested */
365628143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
365728143c3dSStefano Zampini       if (*mat_n) {
365828143c3dSStefano Zampini         PetscMPIInt subcommsize2;
365928143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
366028143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
366128143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
366228143c3dSStefano Zampini       } else {
366328143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
366428143c3dSStefano Zampini       }
366528143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
3666779c1cceSStefano Zampini       PetscMPIInt rank;
3667779c1cceSStefano Zampini 
3668779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
366928143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
367028143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
367128143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3672306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
367328143c3dSStefano Zampini     }
367428143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
367528143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
367628143c3dSStefano Zampini   } else {
367728143c3dSStefano Zampini     comm_n = comm;
367828143c3dSStefano Zampini   }
367928143c3dSStefano Zampini 
3680e7931f94SStefano Zampini   /* prepare send/receive buffers */
3681785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
3682e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
3683785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
3684e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
368528143c3dSStefano Zampini   if (nis) {
3686854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
368728143c3dSStefano Zampini   }
3688e7931f94SStefano Zampini 
368928143c3dSStefano Zampini   /* Get data from local matrices */
3690e7931f94SStefano Zampini   if (!isdense) {
3691a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
3692e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
3693e7931f94SStefano Zampini     /*
3694e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
3695e7931f94SStefano Zampini        send_buffer_idxs should contain:
3696e7931f94SStefano Zampini        - MatType_PRIVATE type
3697e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
3698e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
3699e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
3700e7931f94SStefano Zampini     */
3701e7931f94SStefano Zampini   } else {
3702e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
37033bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
3704854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
3705e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
3706e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
37073bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3708e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
37093bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3710e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
3711e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
3712e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
3713e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
3714c8587f34SStefano Zampini     }
3715c8587f34SStefano Zampini   }
3716e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
371728143c3dSStefano Zampini   /* additional is (if any) */
371828143c3dSStefano Zampini   if (nis) {
371928143c3dSStefano Zampini     PetscMPIInt psum;
372028143c3dSStefano Zampini     PetscInt j;
372128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
372228143c3dSStefano Zampini       PetscInt plen;
372328143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
372428143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
372528143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
372628143c3dSStefano Zampini     }
3727854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
372828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
372928143c3dSStefano Zampini       PetscInt plen;
373028143c3dSStefano Zampini       const PetscInt *is_array_idxs;
373128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
373228143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
373328143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
373428143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
373528143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
373628143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
373728143c3dSStefano Zampini     }
373828143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
373928143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
374028143c3dSStefano Zampini     }
374128143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
374228143c3dSStefano Zampini   }
374328143c3dSStefano Zampini 
3744e7931f94SStefano Zampini   buf_size_idxs = 0;
3745e7931f94SStefano Zampini   buf_size_vals = 0;
374628143c3dSStefano Zampini   buf_size_idxs_is = 0;
3747e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3748e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
3749e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
375028143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
3751e7931f94SStefano Zampini   }
3752785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
3753785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
375495ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
3755e7931f94SStefano Zampini 
3756e7931f94SStefano Zampini   /* get new tags for clean communications */
3757e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
3758e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
375928143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
3760e7931f94SStefano Zampini 
3761e7931f94SStefano Zampini   /* allocate for requests */
3762785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
3763785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
376495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
3765785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
3766785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
376795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
3768e7931f94SStefano Zampini 
3769e7931f94SStefano Zampini   /* communications */
3770e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
3771e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
377228143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
3773e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3774e7931f94SStefano Zampini     source_dest = onodes[i];
3775e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
3776e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
3777e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3778e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
377928143c3dSStefano Zampini     if (nis) {
378028143c3dSStefano 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);
378128143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
378228143c3dSStefano Zampini     }
3783e7931f94SStefano Zampini   }
3784e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
3785e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
3786e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
3787e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
378828143c3dSStefano Zampini     if (nis) {
378928143c3dSStefano 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);
379028143c3dSStefano Zampini     }
3791e7931f94SStefano Zampini   }
3792e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3793e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
3794e7931f94SStefano Zampini 
3795e7931f94SStefano Zampini   /* assemble new l2g map */
3796e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3797e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
37989d30be91SStefano Zampini   new_local_rows = 0;
3799e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
38009d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3801e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3802e7931f94SStefano Zampini   }
38039d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
3804e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
38059d30be91SStefano Zampini   new_local_rows = 0;
3806e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
38079d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
38089d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3809e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3810e7931f94SStefano Zampini   }
38119d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
38129d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
3813e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
3814e7931f94SStefano Zampini 
3815e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
3816e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
3817e7931f94SStefano 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) */
3818e7931f94SStefano Zampini   if (n_recvs) {
381928143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
3820e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
3821e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
3822e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
3823e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
3824e7931f94SStefano Zampini         break;
3825e7931f94SStefano Zampini       }
3826e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
3827e7931f94SStefano Zampini     }
3828e7931f94SStefano Zampini     switch (new_local_type_private) {
382928143c3dSStefano Zampini       case MATDENSE_PRIVATE:
383028143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
3831e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
3832e7931f94SStefano Zampini           bs = 1;
383328143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
383428143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
383528143c3dSStefano Zampini           bs = 1;
383628143c3dSStefano Zampini         }
3837e7931f94SStefano Zampini         break;
3838e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
3839e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
3840e7931f94SStefano Zampini         bs = 1;
3841e7931f94SStefano Zampini         break;
3842e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
3843e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
3844e7931f94SStefano Zampini         break;
3845e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
3846e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
3847e7931f94SStefano Zampini         break;
3848e7931f94SStefano Zampini       default:
38499d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
3850e7931f94SStefano Zampini         break;
3851e7931f94SStefano Zampini     }
385228143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
385328143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
385428143c3dSStefano Zampini     bs = 1;
3855e7931f94SStefano Zampini   }
3856e7931f94SStefano Zampini 
385770cf5478SStefano Zampini   /* create MATIS object if needed */
385870cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
3859e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
3860e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
386170cf5478SStefano Zampini   } else {
386270cf5478SStefano Zampini     /* it also destroys the local matrices */
386370cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
386470cf5478SStefano Zampini   }
386570cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
3866e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
38679d30be91SStefano Zampini 
38689d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
38699d30be91SStefano Zampini 
38709d30be91SStefano Zampini   /* Global to local map of received indices */
38719d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
38729d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
38739d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
38749d30be91SStefano Zampini 
38759d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
38769d30be91SStefano Zampini   buf_size_idxs = 0;
38779d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
38789d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
38799d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
38809d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
38819d30be91SStefano Zampini   }
38829d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
38839d30be91SStefano Zampini 
38849d30be91SStefano Zampini   /* set preallocation */
38859d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
38869d30be91SStefano Zampini   if (!newisdense) {
38879d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
38889d30be91SStefano Zampini 
38899d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
38909d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
38919d30be91SStefano Zampini     if (n_recvs) {
38929d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
38939d30be91SStefano Zampini     }
38949d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
38959d30be91SStefano Zampini       PetscInt j;
38969d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
38979d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
38989d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
38999d30be91SStefano Zampini         }
39009d30be91SStefano Zampini       } else {
39019d30be91SStefano Zampini         /* TODO */
39029d30be91SStefano Zampini       }
39039d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
39049d30be91SStefano Zampini     }
39059d30be91SStefano Zampini     if (new_local_nnz) {
39069d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
39079d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
39089d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
39099d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
39109d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
39119d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
39129d30be91SStefano Zampini     } else {
39139d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
39149d30be91SStefano Zampini     }
39159d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
39169d30be91SStefano Zampini   } else {
39179d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
39189d30be91SStefano Zampini   }
3919e7931f94SStefano Zampini 
3920e7931f94SStefano Zampini   /* set values */
3921e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
39229d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
3923e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3924e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
3925e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
39269d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
3927e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3928e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3929e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
393028143c3dSStefano Zampini     } else {
393128143c3dSStefano Zampini       /* TODO */
3932e7931f94SStefano Zampini     }
3933e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3934e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
3935e7931f94SStefano Zampini   }
3936e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3937e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
393870cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
393970cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
39409d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
39419d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
3942e7931f94SStefano Zampini 
3943dfd14d43SStefano Zampini #if 0
394428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
3945e7931f94SStefano Zampini     Vec       lvec,rvec;
3946e7931f94SStefano Zampini     PetscReal infty_error;
3947e7931f94SStefano Zampini 
39482a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
3949e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
3950e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
3951e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
395270cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
3953e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3954e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
3955e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
3956e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
3957e7931f94SStefano Zampini   }
395828143c3dSStefano Zampini #endif
3959e7931f94SStefano Zampini 
396028143c3dSStefano Zampini   /* assemble new additional is (if any) */
396128143c3dSStefano Zampini   if (nis) {
396228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
396328143c3dSStefano Zampini 
396428143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3965854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
396628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
396728143c3dSStefano Zampini     psum = 0;
396828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
396928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
397028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
397128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
397228143c3dSStefano Zampini         psum += plen;
397328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
397428143c3dSStefano Zampini       }
397528143c3dSStefano Zampini     }
3976854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
3977854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
397828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
397928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
398028143c3dSStefano Zampini     }
398128143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
398228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
398328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
398428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
398528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
398628143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
398728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
398828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
398928143c3dSStefano Zampini       }
399028143c3dSStefano Zampini     }
399128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
399228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
399328143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
399428143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
399528143c3dSStefano Zampini     }
399628143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
399728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
399828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
399928143c3dSStefano Zampini   }
4000e7931f94SStefano Zampini   /* free workspace */
400128143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4002e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4003e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4004e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4005e7931f94SStefano Zampini   if (isdense) {
4006e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4007e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4008e7931f94SStefano Zampini   } else {
4009e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4010e7931f94SStefano Zampini   }
401128143c3dSStefano Zampini   if (nis) {
401228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
401328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
401428143c3dSStefano Zampini   }
4015e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4016e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
401728143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4018e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4019e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
402028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4021e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4022e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4023e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4024e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4025e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
402628143c3dSStefano Zampini   if (nis) {
402728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
402828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
402928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
403028143c3dSStefano Zampini   }
403128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
403228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
403328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
403428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
403528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
403628143c3dSStefano Zampini     }
403753a05cb3SStefano Zampini     *mat_n = NULL;
403828143c3dSStefano Zampini   }
4039e7931f94SStefano Zampini   PetscFunctionReturn(0);
4040e7931f94SStefano Zampini }
4041a57a6d2fSStefano Zampini 
404212edc857SStefano Zampini /* temporary hack into ksp private data structure */
4043af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
404412edc857SStefano Zampini 
4045c8587f34SStefano Zampini #undef __FUNCT__
4046c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4047c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4048c8587f34SStefano Zampini {
4049c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4050c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
405120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
40529881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
405320a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
40546e683305SStefano Zampini   IS                     coarse_is,*isarray;
40556e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
40566e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
4057f9eb5b7dSStefano Zampini   PC                     pc_temp;
4058c8587f34SStefano Zampini   PCType                 coarse_pc_type;
4059c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
4060f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
40614f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
40626e683305SStefano Zampini   Mat                    t_coarse_mat_is;
40636e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
40646e683305SStefano Zampini   PetscMPIInt            all_procs;
406574e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
406668457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
406722bc73bbSStefano Zampini   PetscScalar            *array;
40689881197aSStefano Zampini   PetscErrorCode         ierr;
4069fdc09c96SStefano Zampini 
4070c8587f34SStefano Zampini   PetscFunctionBegin;
4071c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
407268457ee5SStefano 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 */
4073fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
40745a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
4075fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
4076f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4077f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4078f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
4079fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
408051bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
408151bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4082dc4bcba2SStefano Zampini         PC        pc;
4083dc4bcba2SStefano Zampini         PetscBool isbddc;
4084dc4bcba2SStefano Zampini 
4085dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
4086dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4087dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4088dc4bcba2SStefano Zampini         if (isbddc) {
4089dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4090dc4bcba2SStefano Zampini         }
4091727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4092fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
4093fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
4094fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
4095f4ddd8eeSStefano Zampini       }
4096fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4097fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
4098f4ddd8eeSStefano Zampini     }
409970cf5478SStefano Zampini     /* reset any subassembling information */
410070cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
41016e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
41026e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4103fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
4104f4ddd8eeSStefano Zampini   }
4105c8587f34SStefano Zampini 
41066e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
41072b510759SStefano Zampini   im_active = !!(pcis->n);
41082b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
41096e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
41106e683305SStefano Zampini   void_procs = all_procs-active_procs;
41116e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
411274e2c79eSStefano Zampini   redist = PETSC_FALSE;
411322bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
41146e683305SStefano Zampini     csin_ml = PETSC_TRUE;
41156e683305SStefano Zampini     ncoarse_ml = void_procs;
4116779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4117779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
41186e683305SStefano Zampini       csin_ds = PETSC_TRUE;
411918a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
412018a45a71SStefano Zampini       redist = PETSC_TRUE;
412118a45a71SStefano Zampini     } else {
41226e683305SStefano Zampini       csin_ds = PETSC_TRUE;
4123779c1cceSStefano Zampini       ncoarse_ds = active_procs;
4124779c1cceSStefano Zampini       redist = PETSC_TRUE;
412518a45a71SStefano Zampini     }
41266e683305SStefano Zampini   } else {
41276e683305SStefano Zampini     csin_ml = PETSC_FALSE;
41286e683305SStefano Zampini     ncoarse_ml = all_procs;
41296e683305SStefano Zampini     if (void_procs) {
41306e683305SStefano Zampini       csin_ds = PETSC_TRUE;
41316e683305SStefano Zampini       ncoarse_ds = void_procs;
41326e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
41336e683305SStefano Zampini     } else {
4134779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
413574e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
413674e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
413774e2c79eSStefano Zampini         redist = PETSC_TRUE;
413874e2c79eSStefano Zampini       } else {
41396e683305SStefano Zampini         csin_ds = PETSC_FALSE;
41406e683305SStefano Zampini         ncoarse_ds = all_procs;
41416e683305SStefano Zampini       }
41426e683305SStefano Zampini     }
414374e2c79eSStefano Zampini   }
41446e683305SStefano Zampini 
41456e683305SStefano Zampini   /*
41466e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
41476e683305SStefano Zampini     - we have not exceeded the number of levels requested
41486e683305SStefano Zampini     - we can actually subassemble the active processes
41496e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
41506e683305SStefano Zampini   */
41516e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
41526e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
41536e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
41546e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
41556e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4156f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
41572b510759SStefano Zampini     } else {
4158f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
4159c8587f34SStefano Zampini     }
4160c8587f34SStefano Zampini   }
41616e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
41626e683305SStefano Zampini   if (multilevel_allowed) {
41636e683305SStefano Zampini     ncoarse = ncoarse_ml;
41646e683305SStefano Zampini     csin = csin_ml;
416558da7f69SStefano Zampini     redist = PETSC_FALSE;
41666e683305SStefano Zampini   } else {
41676e683305SStefano Zampini     ncoarse = ncoarse_ds;
41686e683305SStefano Zampini     csin = csin_ds;
41696e683305SStefano Zampini   }
4170e7931f94SStefano Zampini 
4171abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
4172abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4173abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4174abbbba34SStefano Zampini 
4175abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
417622bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
417722bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
417822bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
417922bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4180b9b85e73SStefano Zampini #if 0
4181b9b85e73SStefano Zampini   {
4182b9b85e73SStefano Zampini     PetscViewer viewer;
4183b9b85e73SStefano Zampini     char filename[256];
4184b9b85e73SStefano Zampini     sprintf(filename,"local_coarse_mat%d.m",PetscGlobalRank);
4185b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4186b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4187b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
4188b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4189b9b85e73SStefano Zampini   }
4190b9b85e73SStefano Zampini #endif
4191e176bc59SStefano 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);
41926e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
41936e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
41946e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4195abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4196abbbba34SStefano Zampini 
41976e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
41986e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
41996e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
42006e683305SStefano Zampini     const PetscInt         *idxs;
42016e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
42026e683305SStefano Zampini 
42036e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
42040be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
42056e683305SStefano Zampini     /* allocate space for temporary storage */
4206854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4207854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
42086e683305SStefano Zampini     /* allocate for IS array */
42096e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
42106e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
42116e683305SStefano Zampini     nis = nisdofs + nisneu;
4212854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
42136e683305SStefano Zampini     /* dofs splitting */
42146e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
42156e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
42166e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
42176e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
42186e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
42196e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
42206e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
42216e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
42226e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
42236e683305SStefano Zampini     }
42246e683305SStefano Zampini     /* neumann boundaries */
42256e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
42266e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
42276e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
42286e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
42296e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
42306e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
42316e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
42326e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
42336e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
42346e683305SStefano Zampini     }
42356e683305SStefano Zampini     /* free memory */
42366e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
42376e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
42386e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
42396e683305SStefano Zampini   } else {
42406e683305SStefano Zampini     nis = 0;
42416e683305SStefano Zampini     nisdofs = 0;
42426e683305SStefano Zampini     nisneu = 0;
42436e683305SStefano Zampini     isarray = NULL;
42446e683305SStefano Zampini   }
42456e683305SStefano Zampini   /* destroy no longer needed map */
42466e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
42476e683305SStefano Zampini 
42486e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
42496e683305SStefano Zampini   coarse_mat_is = NULL;
42506e683305SStefano Zampini   if (csin) {
42516e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
425274e2c79eSStefano Zampini       if (redist) {
425374e2c79eSStefano Zampini         PetscMPIInt rank;
4254779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
425574e2c79eSStefano Zampini 
425674e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
425758da7f69SStefano Zampini         spc = active_procs/ncoarse;
425858da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
4259779c1cceSStefano Zampini         if (im_active) {
4260779c1cceSStefano Zampini           destsize = 1;
426174e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
426274e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
426374e2c79eSStefano Zampini           } else {
426474e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
426574e2c79eSStefano Zampini           }
426674e2c79eSStefano Zampini         } else {
4267779c1cceSStefano Zampini           destsize = 0;
42686e683305SStefano Zampini         }
4269779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4270779c1cceSStefano Zampini       } else if (csin_type_simple) {
42716e683305SStefano Zampini         PetscMPIInt rank;
42726e683305SStefano Zampini         PetscInt    issize,isidx;
4273779c1cceSStefano Zampini 
42746e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
42756e683305SStefano Zampini         if (im_active) {
42766e683305SStefano Zampini           issize = 1;
42776e683305SStefano Zampini           isidx = (PetscInt)rank;
42786e683305SStefano Zampini         } else {
42796e683305SStefano Zampini           issize = 0;
42806e683305SStefano Zampini           isidx = -1;
42816e683305SStefano Zampini         }
42826e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4283779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
4284b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
42856e683305SStefano Zampini       }
4286779c1cceSStefano Zampini 
4287779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
4288779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
4289779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
4290779c1cceSStefano Zampini         PetscInt *coarse_candidates;
4291779c1cceSStefano Zampini         const PetscInt* tisindices;
4292779c1cceSStefano Zampini 
4293779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
4294779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
4295779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4296779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
4297779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
4298779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
4299779c1cceSStefano Zampini           }
4300779c1cceSStefano Zampini         }
4301779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
4302779c1cceSStefano Zampini 
4303779c1cceSStefano Zampini 
43046e683305SStefano Zampini         if (pcbddc->dbg_flag) {
43056e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
43066e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
43076e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
43086e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
4309779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
43106e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
43116e683305SStefano Zampini           }
43126e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
43136e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
43146e683305SStefano Zampini         }
43156e683305SStefano Zampini         /* shift the pattern on coarse candidates */
43166e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
43176e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
4318854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
43196e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
43206e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
43216e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
43226e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
43236e683305SStefano Zampini       }
43246e683305SStefano Zampini       if (pcbddc->dbg_flag) {
43256e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
43266e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
43276e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
43286e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
43296e683305SStefano Zampini       }
4330779c1cceSStefano Zampini     }
43316e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
433253a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
433353a05cb3SStefano 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);
433453a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
433553a05cb3SStefano 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);
433653a05cb3SStefano Zampini     }
43376e683305SStefano Zampini   } else {
43386e683305SStefano Zampini     if (pcbddc->dbg_flag) {
43396e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
43406e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
43416e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
43426e683305SStefano Zampini     }
43436e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
43446e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
43456e683305SStefano Zampini   }
43466e683305SStefano Zampini 
43476e683305SStefano Zampini   /* create local to global scatters for coarse problem */
434868457ee5SStefano Zampini   if (compute_vecs) {
43496e683305SStefano Zampini     PetscInt lrows;
43506e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
43516e683305SStefano Zampini     if (coarse_mat_is) {
43526e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
43536e683305SStefano Zampini     } else {
43546e683305SStefano Zampini       lrows = 0;
43556e683305SStefano Zampini     }
43566e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
43576e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
43586e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
43596e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
43606e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
43616e683305SStefano Zampini   }
43626e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
43636e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
4364c8587f34SStefano Zampini 
4365f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
4366f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
4367f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
4368f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
4369f9eb5b7dSStefano Zampini   } else {
4370f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
4371f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
4372c8587f34SStefano Zampini   }
4373c8587f34SStefano Zampini 
43746e683305SStefano Zampini   /* print some info if requested */
43756e683305SStefano Zampini   if (pcbddc->dbg_flag) {
43766e683305SStefano Zampini     if (!multilevel_allowed) {
43776e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
43786e683305SStefano Zampini       if (multilevel_requested) {
43796e683305SStefano 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);
43806e683305SStefano Zampini       } else if (pcbddc->max_levels) {
43816e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
43826e683305SStefano Zampini       }
43836e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
43846e683305SStefano Zampini     }
43856e683305SStefano Zampini   }
43866e683305SStefano Zampini 
4387f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
43886e683305SStefano Zampini   if (coarse_mat_is) {
43896e683305SStefano Zampini     MatReuse coarse_mat_reuse;
43906a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
43916e683305SStefano Zampini     if (pcbddc->dbg_flag) {
43926e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
43936e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
43946e683305SStefano Zampini     }
4395f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
4396312be037SStefano Zampini       char prefix[256],str_level[16];
4397e604994aSStefano Zampini       size_t len;
43986e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
4399422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
4400c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
4401f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
44025f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
4403c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
44046e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
4405c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4406c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4407e604994aSStefano Zampini       /* prefix */
4408e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
4409e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4410e604994aSStefano Zampini       if (!pcbddc->current_level) {
4411e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4412e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
4413c8587f34SStefano Zampini       } else {
4414e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4415312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4416312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
441734d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4418312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4419e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
4420e604994aSStefano Zampini       }
4421e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
44223e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
44233e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
44243e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
44253e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
4426f9eb5b7dSStefano Zampini       /* allow user customization */
4427f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
44283e3c6dadSStefano Zampini     }
44293e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
443051bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
44313e3c6dadSStefano Zampini     if (nisdofs) {
44323e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
44333e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
44343e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
44353e3c6dadSStefano Zampini       }
44363e3c6dadSStefano Zampini     }
44373e3c6dadSStefano Zampini     if (nisneu) {
44383e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
44393e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
4440312be037SStefano Zampini     }
4441f9eb5b7dSStefano Zampini 
4442f9eb5b7dSStefano Zampini     /* get some info after set from options */
4443f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
4444f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
44454f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
44466e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
4447f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4448f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
4449f9eb5b7dSStefano Zampini     }
445039f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
44514f3a063dSStefano Zampini     if (isredundant) {
44524f3a063dSStefano Zampini       KSP inner_ksp;
44534f3a063dSStefano Zampini       PC  inner_pc;
44544f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
44554f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
44564f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
44574f3a063dSStefano Zampini     }
4458f9eb5b7dSStefano Zampini 
4459f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
4460fa7f1dd8SStefano Zampini     if (coarse_reuse) {
446181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
4462fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
44636e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
4464fa7f1dd8SStefano Zampini     } else {
44656e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
4466fa7f1dd8SStefano Zampini     }
4467c8587f34SStefano Zampini     if (isbddc || isnn) {
446822bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
446970cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
4470b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
447122b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
44726e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
44736e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
44746e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
44756e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
447622b6e8a2SStefano Zampini           }
447770cf5478SStefano Zampini         }
447853a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
447970cf5478SStefano Zampini       } else {
448022bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
448122bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
448222bc73bbSStefano Zampini       }
448322bc73bbSStefano Zampini     } else {
44842e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
4485c8587f34SStefano Zampini     }
4486c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
4487c8587f34SStefano Zampini 
44883301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
44895a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
44903301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
44913301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
44923301b35fSStefano Zampini     }
44933301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
44943301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
44953301b35fSStefano Zampini     }
44963301b35fSStefano Zampini     if (pc->pmat->spd_set) {
44973301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
44983301b35fSStefano Zampini     }
44996e683305SStefano Zampini     /* set operators */
45005f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
45016e683305SStefano Zampini     if (pcbddc->dbg_flag) {
45026e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
45036e683305SStefano Zampini     }
45046e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
45056e683305SStefano Zampini     coarse_mat = 0;
45066e683305SStefano Zampini   }
45076e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
4508b9b85e73SStefano Zampini #if 0
4509b9b85e73SStefano Zampini   {
4510b9b85e73SStefano Zampini     PetscViewer viewer;
4511b9b85e73SStefano Zampini     char filename[256];
4512b9b85e73SStefano Zampini     sprintf(filename,"coarse_mat.m");
4513b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,filename,&viewer);CHKERRQ(ierr);
4514b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4515b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4516b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4517b9b85e73SStefano Zampini   }
4518b9b85e73SStefano Zampini #endif
4519c8587f34SStefano Zampini 
4520c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4521298c0119SStefano Zampini #if 0
4522c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4523c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
452498a51de6SStefano Zampini   }
4525298c0119SStefano Zampini #endif
452698a51de6SStefano Zampini 
452798a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
452898a51de6SStefano Zampini     Vec crhs,csol;
452998a51de6SStefano Zampini     PetscBool ispreonly;
453004708bb6SStefano Zampini 
453198a51de6SStefano Zampini     if (CoarseNullSpace) {
4532c8587f34SStefano Zampini       if (isbddc) {
4533c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4534c8587f34SStefano Zampini       } else {
45355fa7ec2dSBarry Smith         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
4536c8587f34SStefano Zampini       }
4537c8587f34SStefano Zampini     }
4538f9eb5b7dSStefano Zampini     /* setup coarse ksp */
4539f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4540f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4541f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
45426e683305SStefano Zampini     /* hack */
4543f347579bSStefano Zampini     if (!csol) {
45442a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4545f9eb5b7dSStefano Zampini     }
4546f347579bSStefano Zampini     if (!crhs) {
45472a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4548f347579bSStefano Zampini     }
4549cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4550cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
45516e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4552c8587f34SStefano Zampini       KSP       check_ksp;
45532b510759SStefano Zampini       KSPType   check_ksp_type;
4554c8587f34SStefano Zampini       PC        check_pc;
45556e683305SStefano Zampini       Vec       check_vec,coarse_vec;
45566a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
45572b510759SStefano Zampini       PetscInt  its;
45586e683305SStefano Zampini       PetscBool compute_eigs;
45596e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
45606e683305SStefano Zampini       PetscInt  neigs;
45618e185a42SStefano Zampini       const char *prefix;
4562c8587f34SStefano Zampini 
45632b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
45646e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
4565422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
456623ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4567f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
45682b510759SStefano Zampini       if (ispreonly) {
45692b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
45706e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
45712b510759SStefano Zampini       } else {
4572cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
45736e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4574c8587f34SStefano Zampini       }
4575c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
45766e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
45776e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
45786e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4579a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4580a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4581a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4582a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4583c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4584c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4585c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4586c8587f34SStefano Zampini       /* create random vec */
45876e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
45886e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
4589c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
4590c8587f34SStefano Zampini       if (CoarseNullSpace) {
4591c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
4592c8587f34SStefano Zampini       }
45936e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
4594c8587f34SStefano Zampini       /* solve coarse problem */
45956e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
4596c8587f34SStefano Zampini       if (CoarseNullSpace) {
45976e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
4598c8587f34SStefano Zampini       }
4599cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
46006e683305SStefano Zampini       if (compute_eigs) {
4601854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4602854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
46036e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
46046e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
46056e683305SStefano Zampini         lambda_min = eigs_r[0];
46066e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
46076e683305SStefano Zampini           if (lambda_max>lambda_min) {
4608cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4609cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4610cbcc2c2aSStefano Zampini           }
4611c8587f34SStefano Zampini         }
4612c8587f34SStefano Zampini       }
4613cbcc2c2aSStefano Zampini 
4614c8587f34SStefano Zampini       /* check coarse problem residual error */
46156e683305SStefano Zampini       if (pcbddc->dbg_flag) {
46166e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
46176e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
46186e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4619c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
46206e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
46216e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4622c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
4623779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
46246e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
46256e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
46266e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
46276e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
46286e683305SStefano Zampini         if (compute_eigs) {
46296e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4630deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4631c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
46326e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
46336e683305SStefano 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);
46346e683305SStefano Zampini           for (i=0;i<neigs;i++) {
46356e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4636c8587f34SStefano Zampini           }
46376e683305SStefano Zampini         }
46386e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
46396e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
46406e683305SStefano Zampini       }
4641c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
46426e683305SStefano Zampini       if (compute_eigs) {
46436e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
46446e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4645c8587f34SStefano Zampini       }
46466e683305SStefano Zampini     }
46476e683305SStefano Zampini   }
4648cbcc2c2aSStefano Zampini   /* print additional info */
4649cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
46506e683305SStefano Zampini     /* waits until all processes reaches this point */
46516e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4652cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4653cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4654cbcc2c2aSStefano Zampini   }
4655cbcc2c2aSStefano Zampini 
46562b510759SStefano Zampini   /* free memory */
4657c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4658fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4659c8587f34SStefano Zampini   PetscFunctionReturn(0);
4660c8587f34SStefano Zampini }
4661674ae819SStefano Zampini 
4662f34684f1SStefano Zampini #undef __FUNCT__
4663f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4664f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4665f34684f1SStefano Zampini {
4666f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4667f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
4668f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
4669dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
4670dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
467173be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
4672dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
4673f34684f1SStefano Zampini   PetscErrorCode ierr;
4674f34684f1SStefano Zampini 
4675f34684f1SStefano Zampini   PetscFunctionBegin;
4676f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
46770e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
46780e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
4679727cdba6SStefano Zampini   }
4680dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
46813bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
4682dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
4683dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
4684dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
4685dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
4686dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
4687dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
46880e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
46890e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
46900e6343abSStefano Zampini   }
4691dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
4692dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
4693dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
4694dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
4695dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
4696f34684f1SStefano Zampini 
4697f34684f1SStefano Zampini   /* check numbering */
4698f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
4699f34684f1SStefano Zampini     PetscScalar coarsesum,*array;
4700dc456d91SStefano Zampini     PetscInt    i;
4701b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
4702f34684f1SStefano Zampini 
4703f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4704f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4705f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
47060fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
4707f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4708f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4709727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4710f34684f1SStefano Zampini     }
4711f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4712f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4713f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4714e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4715e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4716e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4717e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4718f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4719f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4720f34684f1SStefano Zampini       if (array[i] == 1.0) {
4721b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
4722f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a single process!\n",PetscGlobalRank,i);CHKERRQ(ierr);
4723f34684f1SStefano Zampini       }
4724f34684f1SStefano Zampini     }
4725b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4726f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4727f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4728f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
4729f34684f1SStefano Zampini     }
4730f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4731f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4732e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4733e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4734f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
4735f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
4736b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
4737ca8b9ea9SStefano Zampini       PetscInt *gidxs;
4738ca8b9ea9SStefano Zampini 
4739ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
47403bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
4741f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
4742f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4743f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4744f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
47454bc2dc4bSStefano 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);
4746f34684f1SStefano Zampini       }
4747f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4748ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
4749f34684f1SStefano Zampini     }
4750f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4751302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
4752f34684f1SStefano Zampini   }
47538bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
4754f34684f1SStefano Zampini   /* get back data */
4755f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
4756f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
4757674ae819SStefano Zampini   PetscFunctionReturn(0);
4758674ae819SStefano Zampini }
4759674ae819SStefano Zampini 
4760e456f2a8SStefano Zampini #undef __FUNCT__
4761e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
4762a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
4763e456f2a8SStefano Zampini {
4764e456f2a8SStefano Zampini   IS             localis_t;
4765a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
4766e456f2a8SStefano Zampini   PetscScalar    *vals;
4767e456f2a8SStefano Zampini   PetscErrorCode ierr;
4768e456f2a8SStefano Zampini 
4769e456f2a8SStefano Zampini   PetscFunctionBegin;
4770a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
4771e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
4772854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
4773e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
4774e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4775a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
4776a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
47771035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
4778a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
47791035eff8SStefano Zampini   }
4780a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
4781e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4782e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
4783a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
4784a7dc3881SStefano Zampini   /* now compute set in local ordering */
4785a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4786a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4787a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4788a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
4789a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4790ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4791e456f2a8SStefano Zampini       lsize++;
4792e456f2a8SStefano Zampini     }
4793e456f2a8SStefano Zampini   }
4794854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
4795a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4796ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4797e456f2a8SStefano Zampini       idxs[lsize++] = i;
4798e456f2a8SStefano Zampini     }
4799e456f2a8SStefano Zampini   }
4800a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4801a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
4802e456f2a8SStefano Zampini   *localis = localis_t;
4803e456f2a8SStefano Zampini   PetscFunctionReturn(0);
4804e456f2a8SStefano Zampini }
4805906d46d4SStefano Zampini 
4806906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
4807906d46d4SStefano Zampini #undef __FUNCT__
4808906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
4809906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
4810906d46d4SStefano Zampini {
4811906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4812906d46d4SStefano Zampini   PetscErrorCode   ierr;
4813906d46d4SStefano Zampini 
4814906d46d4SStefano Zampini   PetscFunctionBegin;
4815906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4816906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4817906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4818906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4819906d46d4SStefano Zampini   PetscFunctionReturn(0);
4820906d46d4SStefano Zampini }
4821906d46d4SStefano Zampini 
4822906d46d4SStefano Zampini #undef __FUNCT__
4823906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
4824906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
4825906d46d4SStefano Zampini {
4826906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4827906d46d4SStefano Zampini   PetscErrorCode   ierr;
4828906d46d4SStefano Zampini 
4829906d46d4SStefano Zampini   PetscFunctionBegin;
4830906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4831906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4832906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4833906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4834906d46d4SStefano Zampini   PetscFunctionReturn(0);
4835906d46d4SStefano Zampini }
4836b96c3477SStefano Zampini 
4837b96c3477SStefano Zampini #undef __FUNCT__
4838b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
483908122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
4840b96c3477SStefano Zampini {
4841a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
4842b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4843b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4844a64f4aa4SStefano Zampini   Mat                 S_j;
4845b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
4846b96c3477SStefano Zampini   PetscBool           free_used_adj;
4847b96c3477SStefano Zampini   PetscErrorCode      ierr;
4848b96c3477SStefano Zampini 
4849b96c3477SStefano Zampini   PetscFunctionBegin;
4850b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
4851b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
485208122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
4853b96c3477SStefano Zampini     used_xadj = NULL;
4854b96c3477SStefano Zampini     used_adjncy = NULL;
4855b96c3477SStefano Zampini   } else {
485608122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
485708122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
485808122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
485908122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
4860b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
4861b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
4862b96c3477SStefano Zampini     } else {
48632fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
4864b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
4865b96c3477SStefano Zampini       PetscInt       nvtxs;
4866b96c3477SStefano Zampini 
48672fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
48682fffb893SStefano Zampini       if (flg_row) {
4869b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
4870b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
4871b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
4872b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
48732fffb893SStefano Zampini       } else {
48742fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
48752fffb893SStefano Zampini         used_xadj = NULL;
48762fffb893SStefano Zampini         used_adjncy = NULL;
48772fffb893SStefano Zampini       }
48782fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4879b96c3477SStefano Zampini     }
4880b96c3477SStefano Zampini   }
4881d5574798SStefano Zampini 
4882d5574798SStefano Zampini   /* setup sub_schurs data */
4883a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
4884a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
4885a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
4886a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
4887*06a4e24aSStefano 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);
4888a64f4aa4SStefano Zampini   } else {
48896816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
489004708bb6SStefano Zampini     PetscBool isseqaij;
48915feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
48925feab87aSStefano Zampini       PetscInt n_vertices;
48935feab87aSStefano Zampini 
48945feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
48952034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
48965feab87aSStefano Zampini     }
489704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
489804708bb6SStefano Zampini     if (!isseqaij) {
489904708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
490004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
490104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
490204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
490304708bb6SStefano Zampini       } else {
490404708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
490504708bb6SStefano Zampini       }
490604708bb6SStefano Zampini     }
4907*06a4e24aSStefano 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);
4908a64f4aa4SStefano Zampini   }
4909a64f4aa4SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
4910b96c3477SStefano Zampini 
4911b96c3477SStefano Zampini   /* free adjacency */
4912b96c3477SStefano Zampini   if (free_used_adj) {
4913b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
4914b96c3477SStefano Zampini   }
4915b96c3477SStefano Zampini   PetscFunctionReturn(0);
4916b96c3477SStefano Zampini }
4917b96c3477SStefano Zampini 
4918b96c3477SStefano Zampini #undef __FUNCT__
4919b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
492008122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
4921b96c3477SStefano Zampini {
4922b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
4923b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4924b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4925b96c3477SStefano Zampini   PCBDDCGraph         graph;
4926b96c3477SStefano Zampini   PetscErrorCode      ierr;
4927b96c3477SStefano Zampini 
4928b96c3477SStefano Zampini   PetscFunctionBegin;
4929b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
493008122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
49313301b35fSStefano Zampini     IS       verticesIS,verticescomm;
49323301b35fSStefano Zampini     PetscInt vsize,*idxs;
4933b96c3477SStefano Zampini 
4934b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
49353301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
49363301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
49373301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
49383301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
49393301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
4940b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
49417fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
49423301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
49433301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
4944b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4945b96c3477SStefano Zampini /*
4946b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
4947b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4948b96c3477SStefano Zampini     }
4949b96c3477SStefano Zampini */
4950b96c3477SStefano Zampini   } else {
4951b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
4952b96c3477SStefano Zampini   }
4953b96c3477SStefano Zampini 
4954b96c3477SStefano Zampini   /* sub_schurs init */
4955a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
4956a64f4aa4SStefano Zampini 
4957b96c3477SStefano Zampini   /* free graph struct */
495808122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
4959b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
4960b96c3477SStefano Zampini   }
4961b96c3477SStefano Zampini   PetscFunctionReturn(0);
4962b96c3477SStefano Zampini }
4963