xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision bbb9e6c6d664ca28960acb626686b45e2eac2b03)
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 
8b1b3d7a2SStefano Zampini #undef __FUNCT__
9b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
1008122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
11b1b3d7a2SStefano Zampini {
12b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1308122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
1408122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
1508122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
1608122e43SStefano Zampini   PetscScalar     *work,lwork;
1708122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
1808122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
1908122e43SStefano Zampini   PetscScalar     *Smult,*Seigv;
2008122e43SStefano Zampini   PetscReal       *eigs,thresh;
2108122e43SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs,maxneigs_r,cumsubs;
2208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2308122e43SStefano Zampini   PetscReal       *rwork;
2408122e43SStefano Zampini #endif
2508122e43SStefano Zampini   PetscBool       symmetric;
26b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
27b1b3d7a2SStefano Zampini 
28b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2908122e43SStefano Zampini   if (!sub_schurs->use_mumps) {
3008122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
3108122e43SStefano Zampini   }
3208122e43SStefano Zampini   ierr = MatIsSymmetric(sub_schurs->A,0.0,&symmetric);CHKERRQ(ierr);
3308122e43SStefano Zampini   if (!symmetric) {
3408122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Not yet implemented");
3508122e43SStefano Zampini   }
3608122e43SStefano Zampini 
3708122e43SStefano Zampini   /* max size of subsets */
3808122e43SStefano Zampini   mss = 0;
3908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
4008122e43SStefano Zampini     if (PetscBTLookup(sub_schurs->computed_Stilda_subs,i)) {
4108122e43SStefano Zampini       PetscInt subset_size;
4208122e43SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
4308122e43SStefano Zampini       mss = PetscMax(mss,subset_size);
4408122e43SStefano Zampini     }
4508122e43SStefano Zampini   }
4608122e43SStefano Zampini 
4708122e43SStefano Zampini   /* min/max and threshold */
4808122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
4908122e43SStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 1;
5008122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
5108122e43SStefano Zampini   if (pcbddc->adaptive_threshold > 1.0) {
5208122e43SStefano Zampini     thresh = 1.0/pcbddc->adaptive_threshold;
5308122e43SStefano Zampini   } else {
5408122e43SStefano Zampini     thresh = 1.0;
5508122e43SStefano Zampini   }
5608122e43SStefano Zampini 
5708122e43SStefano Zampini   /* allocate lapack workspace */
5808122e43SStefano Zampini   cum = cum2 = 0;
5908122e43SStefano Zampini   maxneigs = 0;
6008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
6108122e43SStefano Zampini     if (PetscBTLookup(sub_schurs->computed_Stilda_subs,i)) {
6208122e43SStefano Zampini       PetscInt n,subset_size;
6308122e43SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
6408122e43SStefano Zampini       n = PetscMin(subset_size,nmax);
6508122e43SStefano Zampini       n = PetscMax(n,nmin);
6608122e43SStefano Zampini       cum += subset_size*n;
6708122e43SStefano Zampini       cum2 += n;
6808122e43SStefano Zampini       maxneigs = PetscMax(maxneigs,n);
6908122e43SStefano Zampini     }
7008122e43SStefano Zampini   }
7108122e43SStefano Zampini 
7208122e43SStefano Zampini   if (mss) {
7308122e43SStefano Zampini     if (symmetric) {
7408122e43SStefano Zampini       PetscBLASInt B_itype = 1;
7508122e43SStefano Zampini       PetscBLASInt B_N = mss;
7608122e43SStefano Zampini       PetscScalar  zero = 0.0;
7708122e43SStefano Zampini       PetscScalar  eps = 0.0; /* dlamch? */
7808122e43SStefano Zampini 
7908122e43SStefano Zampini       B_lwork = -1;
8008122e43SStefano Zampini       S = NULL;
8108122e43SStefano Zampini       St = NULL;
8208122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
8308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
8408122e43SStefano 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));
8508122e43SStefano Zampini #else
8608122e43SStefano 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));
8708122e43SStefano Zampini #endif
8808122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
8908122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
9008122e43SStefano Zampini     } else {
9108122e43SStefano Zampini         /* TODO */
9208122e43SStefano Zampini     }
9308122e43SStefano Zampini   } else {
9408122e43SStefano Zampini     lwork = 0;
9508122e43SStefano Zampini   }
9608122e43SStefano Zampini 
9708122e43SStefano Zampini   nv = 0;
9808122e43SStefano Zampini   if (sub_schurs->is_Ej_com) { /* complement of subsets, each entry is a vertex */
9908122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_Ej_com,&nv);CHKERRQ(ierr);
10008122e43SStefano Zampini   }
10108122e43SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)lwork,&B_lwork);CHKERRQ(ierr);
10208122e43SStefano Zampini   ierr = PetscMalloc7(mss*mss,&S,mss*mss,&St,mss*mss,&eigv,mss,&eigs,
10308122e43SStefano Zampini                       B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
10408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
10508122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
10608122e43SStefano Zampini #endif
10708122e43SStefano Zampini   ierr = PetscMalloc2(mss*mss,&Smult,mss*mss,&Seigv);CHKERRQ(ierr);
10808122e43SStefano Zampini   ierr = PetscMalloc4(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
10908122e43SStefano Zampini                       nv+cum2+1,&pcbddc->adaptive_constraints_ptrs,
11008122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
11108122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
11208122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
11308122e43SStefano Zampini 
11408122e43SStefano Zampini   maxneigs = 0;
11508122e43SStefano Zampini   cum = cum2 = cumarray = 0;
11608122e43SStefano Zampini   if (sub_schurs->is_Ej_com) {
11708122e43SStefano Zampini     const PetscInt *idxs;
11808122e43SStefano Zampini 
11908122e43SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_Ej_com,&idxs);CHKERRQ(ierr);
12008122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
12108122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
12208122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
12308122e43SStefano Zampini       pcbddc->adaptive_constraints_ptrs[cum] = cum;
12408122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
12508122e43SStefano Zampini     }
12608122e43SStefano Zampini     cum2 = cum;
12708122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_Ej_com,&idxs);CHKERRQ(ierr);
12808122e43SStefano Zampini   }
12908122e43SStefano Zampini 
13008122e43SStefano Zampini   if (mss) { /* multilevel */
13108122e43SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
13208122e43SStefano Zampini       ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
13308122e43SStefano Zampini     } else {
13408122e43SStefano Zampini       ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all,&Sarray);CHKERRQ(ierr);
13508122e43SStefano Zampini     }
13608122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
13708122e43SStefano Zampini   }
13808122e43SStefano Zampini 
13908122e43SStefano Zampini   cumsubs = 0;
14008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
14108122e43SStefano Zampini     PetscInt j,subset_size;
14208122e43SStefano Zampini 
14308122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
14408122e43SStefano Zampini     if (PetscBTLookup(sub_schurs->computed_Stilda_subs,i)) {
14508122e43SStefano Zampini       const PetscInt *idxs;
14608122e43SStefano Zampini       PetscScalar    one = 1.0,zero=0.0;
14708122e43SStefano Zampini       PetscBLASInt   B_N;
14808122e43SStefano Zampini 
14908122e43SStefano Zampini       /* S should be copied since we need it for deluxe scaling */
15008122e43SStefano Zampini       if (symmetric) {
15108122e43SStefano Zampini         PetscInt j;
15208122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
15308122e43SStefano Zampini           ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
15408122e43SStefano Zampini         }
15508122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
15608122e43SStefano Zampini           ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
15708122e43SStefano Zampini         }
15808122e43SStefano Zampini       } else {
15908122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
16008122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
16108122e43SStefano Zampini       }
16208122e43SStefano Zampini       /* is always this the right matrix? */
16308122e43SStefano Zampini       ierr = PetscMemcpy(Smult,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
16408122e43SStefano Zampini 
16508122e43SStefano Zampini       /* we could reuse space already allocated when building sum_S_Ej_tilda_all */
16608122e43SStefano Zampini       /* St = Starray+cumarray; */
16708122e43SStefano Zampini 
16808122e43SStefano Zampini       if (symmetric) {
16908122e43SStefano Zampini         PetscBLASInt B_itype = 1;
17008122e43SStefano Zampini         PetscBLASInt B_IL = 1, B_IU;
17108122e43SStefano Zampini         PetscScalar  eps = -1.0; /* dlamch? */
17208122e43SStefano Zampini 
17308122e43SStefano Zampini         /* ask for eigenvalues lower than thresh */
17408122e43SStefano Zampini         PetscPrintf(PETSC_COMM_SELF,"[%d] Computing for sub %d/%d.\n",PetscGlobalRank,i,sub_schurs->n_subs);
17508122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
17608122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
17708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
17808122e43SStefano Zampini         PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&zero,&thresh,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
17908122e43SStefano Zampini #else
18008122e43SStefano Zampini         PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&zero,&thresh,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
18108122e43SStefano Zampini #endif
18208122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
18308122e43SStefano Zampini         if (B_ierr) {
18408122e43SStefano Zampini           if (B_ierr < 0 ) {
18508122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
18608122e43SStefano Zampini           } else if (B_ierr <= B_N) {
18708122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
18808122e43SStefano Zampini           } else {
18908122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d principal minor not posdef",(int)B_ierr-B_N-1);
19008122e43SStefano Zampini           }
19108122e43SStefano Zampini         }
19208122e43SStefano Zampini 
19308122e43SStefano Zampini         if (B_neigs > nmax) {
19408122e43SStefano Zampini           PetscPrintf(PETSC_COMM_SELF,"[%d]   found %d eigs, more than required %d.\n",PetscGlobalRank,B_neigs,nmax);
19508122e43SStefano Zampini           B_neigs = nmax;
19608122e43SStefano Zampini         }
19708122e43SStefano Zampini 
19808122e43SStefano Zampini         if (B_neigs < nmin) {
19908122e43SStefano Zampini           PetscBLASInt B_neigs2;
20008122e43SStefano Zampini 
20108122e43SStefano Zampini           B_IL = B_neigs + 1;
20208122e43SStefano Zampini           ierr = PetscBLASIntCast(nmin,&B_IU);CHKERRQ(ierr);
20308122e43SStefano Zampini           PetscPrintf(PETSC_COMM_SELF,"[%d]   found %d eigs, less than required %d. Asking for %d to %d incl (fortran like)\n",PetscGlobalRank,B_neigs,nmin,B_IL,B_IU);
20408122e43SStefano Zampini           if (symmetric) {
20508122e43SStefano Zampini             PetscInt j;
20608122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
20708122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
20808122e43SStefano Zampini             }
20908122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
21008122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
21108122e43SStefano Zampini             }
21208122e43SStefano Zampini           } else {
21308122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
21408122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
21508122e43SStefano Zampini           }
21608122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
21708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
21808122e43SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&zero,&thresh,&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));
21908122e43SStefano Zampini #else
22008122e43SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&zero,&thresh,&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));
22108122e43SStefano Zampini #endif
22208122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
22308122e43SStefano Zampini           B_neigs += B_neigs2;
22408122e43SStefano Zampini         }
22508122e43SStefano Zampini         if (B_ierr) {
22608122e43SStefano Zampini           if (B_ierr < 0 ) {
22708122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
22808122e43SStefano Zampini           } else if (B_ierr <= B_N) {
22908122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
23008122e43SStefano Zampini           } else {
23108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d principal minor not posdef",(int)B_ierr-B_N-1);
23208122e43SStefano Zampini           }
23308122e43SStefano Zampini         }
23408122e43SStefano Zampini         PetscPrintf(PETSC_COMM_SELF,"[%d]   -> Got %d eigs\n",PetscGlobalRank,B_neigs);
23508122e43SStefano Zampini         for (j=0;j<B_neigs;j++) {
23608122e43SStefano Zampini           if (eigs[j] == 0.0) {
23708122e43SStefano Zampini             PetscPrintf(PETSC_COMM_SELF,"[%d]     Inf\n",PetscGlobalRank);
23808122e43SStefano Zampini           } else {
23908122e43SStefano Zampini             PetscPrintf(PETSC_COMM_SELF,"[%d]     %1.6e\n",PetscGlobalRank,1.0/eigs[j]);
24008122e43SStefano Zampini           }
24108122e43SStefano Zampini         }
24208122e43SStefano Zampini       } else {
24308122e43SStefano Zampini           /* TODO */
24408122e43SStefano Zampini       }
24508122e43SStefano Zampini       maxneigs = PetscMax(B_neigs,maxneigs);
24608122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cumsubs+nv] = B_neigs;
24708122e43SStefano Zampini       cumsubs++;
24808122e43SStefano Zampini 
24908122e43SStefano Zampini       ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
25008122e43SStefano Zampini       PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&B_N,&B_neigs,&B_N,&one,Smult,&B_N,eigv,&B_N,&zero,Seigv,&B_N));
25108122e43SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_data+cum2,Seigv,B_neigs*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
25208122e43SStefano Zampini       ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
25308122e43SStefano Zampini       for (j=0;j<B_neigs;j++) {
25408122e43SStefano Zampini #if 0
25508122e43SStefano Zampini         {
25608122e43SStefano Zampini           PetscBLASInt Blas_N,Blas_one = 1.0;
25708122e43SStefano Zampini           PetscScalar norm;
25808122e43SStefano Zampini           ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
25908122e43SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+cum2,&Blas_one,pcbddc->adaptive_constraints_data+cum2,&Blas_one));
26008122e43SStefano Zampini           if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
26108122e43SStefano Zampini             norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
26208122e43SStefano Zampini           } else {
26308122e43SStefano Zampini             norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
26408122e43SStefano Zampini           }
26508122e43SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+cum2,&Blas_one));
266b1b3d7a2SStefano Zampini         }
267b1b3d7a2SStefano Zampini #endif
26808122e43SStefano Zampini         ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+cum2,idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
26908122e43SStefano Zampini         pcbddc->adaptive_constraints_ptrs[cum++] = cum2;
27008122e43SStefano Zampini         cum2 += subset_size;
27108122e43SStefano Zampini       }
27208122e43SStefano Zampini       ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
27308122e43SStefano Zampini     }
27408122e43SStefano Zampini     /* shift for next computation */
27508122e43SStefano Zampini     cumarray += subset_size*subset_size;
27608122e43SStefano Zampini   }
27708122e43SStefano Zampini   pcbddc->adaptive_constraints_ptrs[cum] = cum2;
27808122e43SStefano Zampini   ierr = PetscFree2(Smult,Seigv);CHKERRQ(ierr);
27908122e43SStefano Zampini 
28008122e43SStefano Zampini   if (mss) {
28108122e43SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
28208122e43SStefano Zampini       ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
28308122e43SStefano Zampini     } else {
28408122e43SStefano Zampini       ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_all,&Sarray);CHKERRQ(ierr);
28508122e43SStefano Zampini     }
28608122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
28708122e43SStefano Zampini   }
28808122e43SStefano Zampini   ierr = PetscFree7(S,St,eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
28908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
29008122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
29108122e43SStefano Zampini #endif
29208122e43SStefano Zampini   if (pcbddc->dbg_flag) {
29308122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
29408122e43SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
29508122e43SStefano Zampini   }
29608122e43SStefano Zampini   PetscFunctionReturn(0);
29708122e43SStefano Zampini }
298b1b3d7a2SStefano Zampini 
299674ae819SStefano Zampini #undef __FUNCT__
300c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
301c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
302c8587f34SStefano Zampini {
303c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3048629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
305c8587f34SStefano Zampini   PetscErrorCode ierr;
306c8587f34SStefano Zampini 
307c8587f34SStefano Zampini   PetscFunctionBegin;
308f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
3095e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
310c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
311c8587f34SStefano Zampini 
312684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
3130fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
314684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
315c8587f34SStefano Zampini 
316c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
317b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
318c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
319c8587f34SStefano Zampini   }
320c8587f34SStefano Zampini 
3218629588bSStefano Zampini   /*
3228629588bSStefano Zampini      Setup local correction and local part of coarse basis.
3238629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
3248629588bSStefano Zampini   */
32547f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
3268629588bSStefano Zampini 
3278629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
3288629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
3298629588bSStefano Zampini 
3308629588bSStefano Zampini   /* free */
3318629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
332c8587f34SStefano Zampini   PetscFunctionReturn(0);
333c8587f34SStefano Zampini }
334c8587f34SStefano Zampini 
335c8587f34SStefano Zampini #undef __FUNCT__
336674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
337674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
338674ae819SStefano Zampini {
339674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
340674ae819SStefano Zampini   PetscErrorCode ierr;
341674ae819SStefano Zampini 
342674ae819SStefano Zampini   PetscFunctionBegin;
343674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
344674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
345674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
346674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
347785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
348674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
349f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
350f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
351785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
35263602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
35363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
354674ae819SStefano Zampini   PetscFunctionReturn(0);
355674ae819SStefano Zampini }
356674ae819SStefano Zampini 
357674ae819SStefano Zampini #undef __FUNCT__
358674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
359674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
360674ae819SStefano Zampini {
361674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
362674ae819SStefano Zampini   PetscErrorCode ierr;
363674ae819SStefano Zampini 
364674ae819SStefano Zampini   PetscFunctionBegin;
365b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
366674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
367674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
368674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
369b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
370674ae819SStefano Zampini   PetscFunctionReturn(0);
371674ae819SStefano Zampini }
372674ae819SStefano Zampini 
373674ae819SStefano Zampini #undef __FUNCT__
374674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
375674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
376674ae819SStefano Zampini {
377674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
37806656605SStefano Zampini   PetscScalar    *array;
379674ae819SStefano Zampini   PetscErrorCode ierr;
380674ae819SStefano Zampini 
381674ae819SStefano Zampini   PetscFunctionBegin;
382674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
383674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
38406656605SStefano Zampini   ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
38506656605SStefano Zampini   ierr = PetscFree(array);CHKERRQ(ierr);
386674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
387674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
38815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
38915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
390674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
391674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
39206656605SStefano Zampini   if (pcbddc->local_auxmat2) {
39306656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
39406656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
39506656605SStefano Zampini   }
396674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
39706656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
398674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
399674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
4008ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
401674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
402674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
403674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
404f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
405f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
406f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
407f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
408727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
409f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
41070cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
4116e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
412674ae819SStefano Zampini   PetscFunctionReturn(0);
413674ae819SStefano Zampini }
414674ae819SStefano Zampini 
415674ae819SStefano Zampini #undef __FUNCT__
416f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
417f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
4186bfb1811SStefano Zampini {
4196bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4206bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4216bfb1811SStefano Zampini   VecType        impVecType;
422e9189074SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
4236bfb1811SStefano Zampini   PetscErrorCode ierr;
4246bfb1811SStefano Zampini 
4256bfb1811SStefano Zampini   PetscFunctionBegin;
426f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
427f4ddd8eeSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
428f4ddd8eeSStefano Zampini   }
429e7b262bdSStefano Zampini   /* get sizes */
430e9189074SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->n_actual_vertices;
431e9189074SStefano Zampini   n_R = pcis->n-pcbddc->n_actual_vertices;
4326bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
433e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
434e7b262bdSStefano Zampini   /* R nodes */
435e7b262bdSStefano Zampini   old_size = -1;
436e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
437e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
438e7b262bdSStefano Zampini   }
439e7b262bdSStefano Zampini   if (n_R != old_size) {
440e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
441e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
4426bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
4436bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
4446bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
4456bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
446e7b262bdSStefano Zampini   }
447e7b262bdSStefano Zampini   /* local primal dofs */
448e7b262bdSStefano Zampini   old_size = -1;
449e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
450e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
451e7b262bdSStefano Zampini   }
452e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
453e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
45483b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
455e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
4566bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
457e7b262bdSStefano Zampini   }
458e7b262bdSStefano Zampini   /* local explicit constraints */
459e7b262bdSStefano Zampini   old_size = -1;
460e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
461e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
462e7b262bdSStefano Zampini   }
463e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
464e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
46583b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
46683b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
46783b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
46883b7ccabSStefano Zampini   }
4696bfb1811SStefano Zampini   PetscFunctionReturn(0);
4706bfb1811SStefano Zampini }
4716bfb1811SStefano Zampini 
4726bfb1811SStefano Zampini #undef __FUNCT__
47347f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
47447f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
47588ebb749SStefano Zampini {
47625084f0cSStefano Zampini   PetscErrorCode         ierr;
47725084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
47888ebb749SStefano Zampini   PC_IS*                 pcis = (PC_IS*)pc->data;
47988ebb749SStefano Zampini   PC_BDDC*               pcbddc = (PC_BDDC*)pc->data;
48025084f0cSStefano Zampini   /* submatrices of local problem */
48188ebb749SStefano Zampini   Mat                    A_RV,A_VR,A_VV;
48206656605SStefano Zampini   /* submatrices of local coarse problem */
48306656605SStefano Zampini   Mat                    S_VV,S_CV,S_VC,S_CC;
48425084f0cSStefano Zampini   /* working matrices */
48506656605SStefano Zampini   Mat                    C_CR;
48625084f0cSStefano Zampini   /* additional working stuff */
48706656605SStefano Zampini   PC                     pc_R;
48806656605SStefano Zampini   Mat                    F;
48906656605SStefano Zampini   PetscBool              isLU,isCHOL,isILU;
49006656605SStefano Zampini 
49125084f0cSStefano Zampini   PetscScalar            *coarse_submat_vals; /* TODO: use a PETSc matrix */
49206656605SStefano Zampini   PetscScalar            *work;
49306656605SStefano Zampini   PetscInt               *idx_V_B;
49406656605SStefano Zampini   PetscInt               n,n_vertices,n_constraints;
49506656605SStefano Zampini   PetscInt               i,n_R,n_D,n_B;
496b9d89cd5SStefano Zampini   PetscBool              unsymmetric_check;
49745a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
49888ebb749SStefano Zampini   MatType                impMatType;
49925084f0cSStefano Zampini   /* some shortcuts to scalars */
50006656605SStefano Zampini   PetscScalar            one=1.0,m_one=-1.0;
50188ebb749SStefano Zampini 
50288ebb749SStefano Zampini   PetscFunctionBegin;
503e9189074SStefano Zampini   /* get number of vertices (corners plus constraints with change of basis)
504e9189074SStefano Zampini      pcbddc->n_actual_vertices stores the actual number of vertices, pcbddc->n_vertices the number of corners computed */
505e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
50688ebb749SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
50788ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
50888ebb749SStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
50988ebb749SStefano Zampini   n_R = pcis->n-n_vertices;
51088ebb749SStefano Zampini 
51188ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
51288ebb749SStefano Zampini   impMatType = MATSEQDENSE;
51388ebb749SStefano Zampini 
51488ebb749SStefano Zampini   /* vertices in boundary numbering */
515785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
5165e8657edSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->primal_indices_local_idxs,&i,idx_V_B);CHKERRQ(ierr);
51788ebb749SStefano Zampini   if (i != n_vertices) {
51822d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
51988ebb749SStefano Zampini   }
52088ebb749SStefano Zampini 
52106656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
52206656605SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
52306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
52406656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
52506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
52606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
52706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
52806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
52906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
53006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
53106656605SStefano Zampini 
53206656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
53306656605SStefano Zampini   /* allocate workspace */
53406656605SStefano Zampini   n = 0;
53506656605SStefano Zampini   if (n_constraints) {
53606656605SStefano Zampini     n += n_R*n_constraints;
53706656605SStefano Zampini   }
53806656605SStefano Zampini   if (n_vertices) {
53906656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
54006656605SStefano Zampini   }
54106656605SStefano Zampini   if (!pcbddc->issym) {
54206656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
54306656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
54406656605SStefano Zampini   }
54506656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
54606656605SStefano Zampini 
54706656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
54806656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
54906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
55006656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
55106656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
55206656605SStefano Zampini   if (isLU || isILU || isCHOL) {
55306656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
55406656605SStefano Zampini   } else {
55506656605SStefano Zampini     F = NULL;
55606656605SStefano Zampini   }
55706656605SStefano Zampini 
55888ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
55988ebb749SStefano Zampini   if (n_constraints) {
56006656605SStefano Zampini     Mat M1,M2,M3;
56106656605SStefano Zampini     IS  is_aux;
562f4ddd8eeSStefano Zampini     /* see if we can save some allocations */
563f4ddd8eeSStefano Zampini     if (pcbddc->local_auxmat2) {
564f4ddd8eeSStefano Zampini       PetscInt on_R,on_constraints;
565f4ddd8eeSStefano Zampini       ierr = MatGetSize(pcbddc->local_auxmat2,&on_R,&on_constraints);CHKERRQ(ierr);
566f4ddd8eeSStefano Zampini       if (on_R != n_R || on_constraints != n_constraints) {
56706656605SStefano Zampini         PetscScalar *marray;
56806656605SStefano Zampini 
56906656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->local_auxmat2,&marray);CHKERRQ(ierr);
57006656605SStefano Zampini         ierr = PetscFree(marray);CHKERRQ(ierr);
571f4ddd8eeSStefano Zampini         ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
572f4ddd8eeSStefano Zampini         ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
573f4ddd8eeSStefano Zampini       }
574f4ddd8eeSStefano Zampini     }
57545a1bb75SStefano Zampini     /* auxiliary matrices */
576f4ddd8eeSStefano Zampini     if (!pcbddc->local_auxmat2) {
57706656605SStefano Zampini       PetscScalar *marray;
57806656605SStefano Zampini 
57906656605SStefano Zampini       ierr = PetscMalloc1(2*n_R*n_constraints,&marray);CHKERRQ(ierr);
58006656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,marray,&pcbddc->local_auxmat2);CHKERRQ(ierr);
58106656605SStefano Zampini       marray += n_R*n_constraints;
58206656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_R,marray,&pcbddc->local_auxmat1);CHKERRQ(ierr);
583f4ddd8eeSStefano Zampini     }
58488ebb749SStefano Zampini 
58525084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
58625084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
5878ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
58825084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
58988ebb749SStefano Zampini 
59088ebb749SStefano Zampini     /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
59106656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
59288ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
59306656605SStefano Zampini       const PetscScalar *row_cmat_values;
59406656605SStefano Zampini       const PetscInt    *row_cmat_indices;
59506656605SStefano Zampini       PetscInt          size_of_constraint,j;
59688ebb749SStefano Zampini 
59706656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
59806656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
59906656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
60006656605SStefano Zampini       }
60106656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
60206656605SStefano Zampini     }
60306656605SStefano Zampini     if (F) {
60406656605SStefano Zampini       Mat B;
60506656605SStefano Zampini 
60606656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
60706656605SStefano Zampini       ierr = MatMatSolve(F,B,pcbddc->local_auxmat2);CHKERRQ(ierr);
60806656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
60906656605SStefano Zampini     } else {
61006656605SStefano Zampini       PetscScalar *xarray;
61106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&xarray);CHKERRQ(ierr);
61206656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
61306656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
61406656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,xarray+i*n_R);CHKERRQ(ierr);
61506656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
61606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
61706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
61806656605SStefano Zampini       }
61906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&xarray);CHKERRQ(ierr);
62006656605SStefano Zampini     }
62106656605SStefano Zampini 
62206656605SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
62306656605SStefano Zampini     ierr = MatConvert(C_CR,impMatType,MAT_REUSE_MATRIX,&C_CR);CHKERRQ(ierr);
62425084f0cSStefano Zampini     ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
62506656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
62606656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
62725084f0cSStefano Zampini     ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
62806656605SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,m_one);CHKERRQ(ierr);
62906656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
63025084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
63125084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
63225084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
63306656605SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CR} needed by BDDC application in KSP and in preproc */
634f4ddd8eeSStefano Zampini     ierr = MatMatMult(M1,C_CR,MAT_REUSE_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
63506656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
63606656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
63788ebb749SStefano Zampini   }
63888ebb749SStefano Zampini 
63988ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
64088ebb749SStefano Zampini   if (n_vertices) {
64106656605SStefano Zampini     Mat       newmat;
64206656605SStefano Zampini     IS        is_aux;
6433a50541eSStefano Zampini     PetscInt  ibs,mbs;
6443a50541eSStefano Zampini     PetscBool issbaij;
6453a50541eSStefano Zampini 
6463a50541eSStefano Zampini     ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
6479577ea80SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
6489577ea80SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
6493a50541eSStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ */
6509577ea80SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
6519577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
6529577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
6539577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
6549577ea80SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
6559577ea80SStefano Zampini     } else {
6563a50541eSStefano Zampini       /* this is safe */
6579577ea80SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
6583a50541eSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
6593a50541eSStefano Zampini       if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
6603a50541eSStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
6613a50541eSStefano Zampini         ierr = MatGetSubMatrix(newmat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
66206656605SStefano Zampini         ierr = MatTranspose(A_VR,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
6633a50541eSStefano Zampini         ierr = MatDestroy(&newmat);CHKERRQ(ierr);
6643a50541eSStefano Zampini       } else {
6659577ea80SStefano Zampini         ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
6669577ea80SStefano Zampini         ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
6679577ea80SStefano Zampini       }
6683a50541eSStefano Zampini     }
66925084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
67088ebb749SStefano Zampini   }
67188ebb749SStefano Zampini 
67288ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
673f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
67406656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
67506656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
67606656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
67706656605SStefano Zampini     }
678f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
67906656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
68006656605SStefano Zampini       PetscScalar *marray;
68106656605SStefano Zampini 
68206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
68306656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
684f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
685f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
686f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
687f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
688f4ddd8eeSStefano Zampini     }
689f4ddd8eeSStefano Zampini   }
69006656605SStefano Zampini 
691f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
69206656605SStefano Zampini     PetscScalar *marray;
69388ebb749SStefano Zampini 
69406656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
6958eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
69606656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
69788ebb749SStefano Zampini     }
698b9d89cd5SStefano Zampini     if (!pcbddc->issym) {
69906656605SStefano Zampini       n *= 2;
700f4ddd8eeSStefano Zampini     }
70106656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
70206656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
70306656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
70406656605SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
70506656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
70606656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
70788ebb749SStefano Zampini     }
70806656605SStefano Zampini     if (!pcbddc->issym) {
70906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
71006656605SStefano Zampini       if (pcbddc->switch_static) {
71106656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
71206656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
71388ebb749SStefano Zampini       }
71488ebb749SStefano Zampini     } else {
715c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
716c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
71706656605SStefano Zampini       if (pcbddc->switch_static) {
718c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
719c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
720c0553b1fSStefano Zampini       }
72188ebb749SStefano Zampini     }
72206656605SStefano Zampini   }
72306656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
72406656605SStefano Zampini   /* vertices */
72506656605SStefano Zampini   if (n_vertices) {
72606656605SStefano Zampini     Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
72706656605SStefano Zampini     PetscScalar  *x,*y;
72806656605SStefano Zampini     PetscBLASInt B_N,B_one = 1;
72906656605SStefano Zampini 
73006656605SStefano Zampini     ierr = PetscMemzero(work,2*n_R*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
73106656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
73206656605SStefano Zampini     ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
73306656605SStefano Zampini     if (F) {
73406656605SStefano Zampini       ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
73506656605SStefano Zampini     } else {
73606656605SStefano Zampini       ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
73706656605SStefano Zampini       for (i=0;i<n_vertices;i++) {
73806656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
73906656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
74006656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
74106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
74206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
74306656605SStefano Zampini       }
74406656605SStefano Zampini       ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
74506656605SStefano Zampini     }
74606656605SStefano Zampini     ierr = MatScale(A_RRmA_RV,m_one);CHKERRQ(ierr);
74706656605SStefano Zampini     /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
74806656605SStefano Zampini     if (n_constraints) {
74906656605SStefano Zampini       Mat B;
75006656605SStefano Zampini       ierr = MatMatMult(pcbddc->local_auxmat1,A_RRmA_RV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
75106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
75206656605SStefano Zampini       ierr = MatMatMult(pcbddc->local_auxmat2,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
75306656605SStefano Zampini       ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
75406656605SStefano Zampini       ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
75506656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
75606656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
75706656605SStefano Zampini     }
75806656605SStefano Zampini     ierr = MatConvert(A_VR,impMatType,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
75906656605SStefano Zampini     ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
76006656605SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
76106656605SStefano Zampini     ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
76206656605SStefano Zampini     ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
76306656605SStefano Zampini     ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
76406656605SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
76506656605SStefano Zampini     ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
76606656605SStefano Zampini     ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
76706656605SStefano Zampini     ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
76806656605SStefano Zampini     ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
76906656605SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
77006656605SStefano Zampini     /* coarse basis functions */
77106656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
77206656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
77306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
77406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
77506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
77606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
77706656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
77806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
77906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
78006656605SStefano Zampini 
78106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
78206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
78306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
78406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
78506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
78606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
78706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
78806656605SStefano Zampini       }
78906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
79006656605SStefano Zampini     }
79106656605SStefano Zampini     ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
79206656605SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
79306656605SStefano Zampini   }
79406656605SStefano Zampini 
79506656605SStefano Zampini   if (n_constraints) {
79606656605SStefano Zampini     Mat B;
79706656605SStefano Zampini 
79806656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
79906656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
80006656605SStefano Zampini     ierr = MatMatMult(pcbddc->local_auxmat2,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
80106656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
80206656605SStefano Zampini     if (n_vertices) {
80306656605SStefano Zampini       ierr = MatMatMult(A_VR,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_VC);CHKERRQ(ierr);
80406656605SStefano Zampini     }
80506656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
80606656605SStefano Zampini     /* coarse basis functions */
80706656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
80806656605SStefano Zampini       PetscScalar *y;
80906656605SStefano Zampini 
81006656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
81106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
81206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
81306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
81406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
81506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
81606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
81706656605SStefano Zampini 
81806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
81906656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
82006656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
82106656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
82206656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
82306656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
82406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
82506656605SStefano Zampini       }
82606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
82706656605SStefano Zampini     }
82806656605SStefano Zampini   }
82906656605SStefano Zampini 
83006656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
83106656605SStefano Zampini   if (!pcbddc->issym) {
83206656605SStefano Zampini     Mat B,X;
83306656605SStefano Zampini 
83406656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,pcbddc->local_primal_size,work,&B);CHKERRQ(ierr);
83506656605SStefano Zampini 
83606656605SStefano Zampini     if (n_constraints) {
83706656605SStefano Zampini       Mat S_VCT,S_CCT,B_C;
83806656605SStefano Zampini 
83906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
84006656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
84106656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
84206656605SStefano Zampini       if (n_vertices) {
84306656605SStefano Zampini         Mat B_V;
84406656605SStefano Zampini 
84506656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
84606656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
84706656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
84806656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
84906656605SStefano Zampini       }
85006656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
85106656605SStefano Zampini     }
85206656605SStefano Zampini     if (n_vertices) {
85306656605SStefano Zampini       Mat          A_VRT;
85406656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
85506656605SStefano Zampini 
85606656605SStefano Zampini       if (!n_constraints) { /* if there are no constraints, reset work */
85706656605SStefano Zampini         ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
85806656605SStefano Zampini       }
85906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+pcbddc->local_primal_size*n_R,&A_VRT);CHKERRQ(ierr);
86006656605SStefano Zampini       ierr = MatTranspose(A_VR,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
86106656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
86206656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,work+pcbddc->local_primal_size*n_R,&B_one,work,&B_one));
86306656605SStefano Zampini     }
86406656605SStefano Zampini 
86506656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,pcbddc->local_primal_size,work+pcbddc->local_primal_size*n_R,&X);CHKERRQ(ierr);
86606656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
86706656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
86806656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
86906656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
87006656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
87106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
87206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
87306656605SStefano Zampini       }
87406656605SStefano Zampini     } else {
87506656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
87606656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
87706656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
87806656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
87906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
88006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
88106656605SStefano Zampini       }
88206656605SStefano Zampini     }
88306656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
88406656605SStefano Zampini     /* coarse basis functions */
88506656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
88606656605SStefano Zampini       PetscScalar *y;
88706656605SStefano Zampini 
88806656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
88906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
89006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
89106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
89206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
89306656605SStefano Zampini       if (i<n_vertices) {
89406656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
89506656605SStefano Zampini       }
89606656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
89706656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
89806656605SStefano Zampini 
89906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
90006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
90106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
90206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
90306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
90406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
90506656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
90606656605SStefano Zampini       }
90706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
90806656605SStefano Zampini     }
90906656605SStefano Zampini     ierr = MatDestroy(&X);CHKERRQ(ierr);
91006656605SStefano Zampini   }
91106656605SStefano Zampini 
91288ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
91306656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
91406656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
91506656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
91606656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
91788ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
91888ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
91988ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
92025084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
92188ebb749SStefano Zampini     Mat         coarse_sub_mat;
92225084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
92388ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
92488ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
92588ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
92688ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
92788ebb749SStefano Zampini     PetscReal   real_value;
92888ebb749SStefano Zampini 
92988ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
93088ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
93188ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
93288ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
93388ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
93488ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
935c0553b1fSStefano Zampini     if (unsymmetric_check) {
93688ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
93788ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
93888ebb749SStefano Zampini     }
93988ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
94088ebb749SStefano Zampini 
94125084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
94206656605SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation\n");CHKERRQ(ierr);
94325084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
944c0553b1fSStefano Zampini     if (unsymmetric_check) {
94588ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
94688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
94788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
94888ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
94988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
95088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
95188ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
95288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
95388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
95488ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
95588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
95688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
95788ebb749SStefano Zampini     } else {
95888ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
95988ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
96088ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
96188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
96288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
96388ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
96488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
96588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
96688ebb749SStefano Zampini     }
96788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
96888ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
96988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
97088ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
97181d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
97288ebb749SStefano Zampini     ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
97306656605SStefano Zampini 
9740fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
97506656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
97625084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
97788ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
97888ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
97988ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
98088ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
98188ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
98288ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
98388ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
98488ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
98588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
98688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
987c0553b1fSStefano Zampini     if (unsymmetric_check) {
98888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
98988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
99088ebb749SStefano Zampini     }
99188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
99288ebb749SStefano Zampini   }
99306656605SStefano Zampini 
99488ebb749SStefano Zampini   /* free memory */
99506656605SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
99688ebb749SStefano Zampini   if (n_vertices) {
99788ebb749SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
99888ebb749SStefano Zampini   }
99988ebb749SStefano Zampini   if (n_constraints) {
100088ebb749SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
100188ebb749SStefano Zampini   }
10028629588bSStefano Zampini   /* get back data */
10038629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
100488ebb749SStefano Zampini   PetscFunctionReturn(0);
100588ebb749SStefano Zampini }
100688ebb749SStefano Zampini 
100788ebb749SStefano Zampini #undef __FUNCT__
1008d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1009b96c3477SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, MatStructure reuse, Mat* B)
1010d65f70fdSStefano Zampini {
1011d65f70fdSStefano Zampini   Mat            *work_mat;
1012d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1013d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1014d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1015d65f70fdSStefano Zampini   PetscErrorCode ierr;
1016d65f70fdSStefano Zampini 
1017d65f70fdSStefano Zampini   PetscFunctionBegin;
1018d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1019d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1020d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1021d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1022d65f70fdSStefano Zampini 
1023d65f70fdSStefano Zampini   if (!rsorted) {
1024d65f70fdSStefano Zampini     const PetscInt *idxs;
1025d65f70fdSStefano Zampini     PetscInt *idxs_sorted,i;
1026d65f70fdSStefano Zampini 
1027d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1028d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1029d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1030d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1031d65f70fdSStefano Zampini     }
1032d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1033d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1034d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1035d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1036d65f70fdSStefano Zampini     }
1037d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1038d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1039d65f70fdSStefano Zampini   } else {
1040d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1041d65f70fdSStefano Zampini     isrow_s = isrow;
1042d65f70fdSStefano Zampini   }
1043d65f70fdSStefano Zampini 
1044d65f70fdSStefano Zampini   if (!csorted) {
1045d65f70fdSStefano Zampini     if (isrow == iscol) {
1046d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1047d65f70fdSStefano Zampini       iscol_s = isrow_s;
1048d65f70fdSStefano Zampini     } else {
1049d65f70fdSStefano Zampini       const PetscInt *idxs;
1050d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1051d65f70fdSStefano Zampini 
1052d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1053d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1054d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1055d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1056d65f70fdSStefano Zampini       }
1057d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1058d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1059d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1060d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1061d65f70fdSStefano Zampini       }
1062d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1063d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1064d65f70fdSStefano Zampini     }
1065d65f70fdSStefano Zampini   } else {
1066d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1067d65f70fdSStefano Zampini     iscol_s = iscol;
1068d65f70fdSStefano Zampini   }
1069d65f70fdSStefano Zampini 
1070b96c3477SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,reuse,&work_mat);CHKERRQ(ierr);
1071d65f70fdSStefano Zampini 
1072d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1073d65f70fdSStefano Zampini     Mat      new_mat;
1074d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1075d65f70fdSStefano Zampini 
1076d65f70fdSStefano Zampini     if (!rsorted) {
1077d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1078d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1079d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1080d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1081d65f70fdSStefano Zampini       }
1082d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1083d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1084d65f70fdSStefano Zampini     } else {
1085d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1086d65f70fdSStefano Zampini     }
1087d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1088d65f70fdSStefano Zampini 
1089d65f70fdSStefano Zampini     if (!csorted) {
1090d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1091d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1092d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1093d65f70fdSStefano Zampini       } else {
1094d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1095d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1096d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1097d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1098d65f70fdSStefano Zampini         }
1099d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1100d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1101d65f70fdSStefano Zampini       }
1102d65f70fdSStefano Zampini     } else {
1103d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1104d65f70fdSStefano Zampini     }
1105d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1106d65f70fdSStefano Zampini 
1107d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1108d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1109d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1110d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1111d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1112d65f70fdSStefano Zampini   }
1113d65f70fdSStefano Zampini 
1114d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1115d65f70fdSStefano Zampini   *B = work_mat[0];
1116d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1117d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1118d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1119d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1120d65f70fdSStefano Zampini }
1121d65f70fdSStefano Zampini 
1122d65f70fdSStefano Zampini #undef __FUNCT__
11235e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
11245e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1125aa0d41d4SStefano Zampini {
1126aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
11275e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1128d65f70fdSStefano Zampini   Mat            new_mat;
11295e8657edSStefano Zampini   IS             is_local,is_global;
1130d65f70fdSStefano Zampini   PetscInt       local_size;
1131d65f70fdSStefano Zampini   PetscBool      isseqaij;
1132aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1133aa0d41d4SStefano Zampini 
1134aa0d41d4SStefano Zampini   PetscFunctionBegin;
1135aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
11365e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
11375e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1138906d46d4SStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(matis->mapping,is_local,&is_global);CHKERRQ(ierr);
1139906d46d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1140b96c3477SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,MAT_INITIAL_MATRIX,&new_mat);CHKERRQ(ierr);
1141906d46d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1142906d46d4SStefano Zampini 
1143906d46d4SStefano Zampini   /* check */
1144906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
1145906d46d4SStefano Zampini     Vec       x,x_change;
1146906d46d4SStefano Zampini     PetscReal error;
1147906d46d4SStefano Zampini 
11485e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1149906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
11505e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
11515e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11525e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1153d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
11545e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11555e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1156906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1157906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1158906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1159906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1160906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
1161906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1162906d46d4SStefano Zampini   }
1163906d46d4SStefano Zampini 
116422d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
11659b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
116622d5777bSStefano Zampini   if (isseqaij) {
1167d65f70fdSStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1168aa0d41d4SStefano Zampini   } else {
1169aa0d41d4SStefano Zampini     Mat work_mat;
1170aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1171d65f70fdSStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1172aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
1173aa0d41d4SStefano Zampini   }
1174d65f70fdSStefano Zampini   ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
117545a1bb75SStefano Zampini   /*
117645a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1177d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
117845a1bb75SStefano Zampini   */
1179d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
1180aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
1181aa0d41d4SStefano Zampini }
1182aa0d41d4SStefano Zampini 
1183aa0d41d4SStefano Zampini #undef __FUNCT__
1184a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
11858ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
1186a64d13efSStefano Zampini {
1187a64d13efSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
1188a64d13efSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
11898ce42a96SStefano Zampini   IS             is_aux1,is_aux2;
1190e9189074SStefano Zampini   PetscInt       *aux_array1,*aux_array2,*is_indices,*idx_R_local;
11913a50541eSStefano Zampini   PetscInt       n_vertices,i,j,n_R,n_D,n_B;
11923a50541eSStefano Zampini   PetscInt       vbs,bs;
11934641a718SStefano Zampini   PetscBT        bitmask;
1194a64d13efSStefano Zampini   PetscErrorCode ierr;
1195a64d13efSStefano Zampini 
1196a64d13efSStefano Zampini   PetscFunctionBegin;
1197b23d619eSStefano Zampini   /*
1198b23d619eSStefano Zampini     No need to setup local scatters if
1199b23d619eSStefano Zampini       - primal space is unchanged
1200b23d619eSStefano Zampini         AND
1201b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
1202b23d619eSStefano Zampini         AND
1203b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
1204b23d619eSStefano Zampini   */
1205b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
1206f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
1207f4ddd8eeSStefano Zampini   }
1208f4ddd8eeSStefano Zampini   /* destroy old objects */
1209f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1210f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1211f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1212a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
1213a64d13efSStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
1214e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
12154641a718SStefano Zampini   /* create auxiliary bitmask */
12164641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
12174641a718SStefano Zampini   for (i=0;i<n_vertices;i++) {
1218e9189074SStefano Zampini     ierr = PetscBTSet(bitmask,pcbddc->primal_indices_local_idxs[i]);CHKERRQ(ierr);
12194641a718SStefano Zampini   }
12203a50541eSStefano Zampini 
1221a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
1222854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
1223a64d13efSStefano Zampini   for (i=0, n_R=0; i<pcis->n; i++) {
12244641a718SStefano Zampini     if (!PetscBTLookup(bitmask,i)) {
1225a64d13efSStefano Zampini       idx_R_local[n_R] = i;
1226a64d13efSStefano Zampini       n_R++;
1227a64d13efSStefano Zampini     }
1228a64d13efSStefano Zampini   }
12293a50541eSStefano Zampini 
12303a50541eSStefano Zampini   /* Block code */
12313a50541eSStefano Zampini   vbs = 1;
12323a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
12333a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
12343a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
12353a50541eSStefano Zampini     PetscInt  *vary;
12363a50541eSStefano Zampini     /* Verify if the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
1237785e854fSJed Brown     ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
12383a50541eSStefano Zampini     ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
1239e9189074SStefano Zampini     for (i=0; i<n_vertices; i++) vary[pcbddc->primal_indices_local_idxs[i]/bs]++;
12403a50541eSStefano Zampini     for (i=0; i<n_vertices; i++) {
12413a50541eSStefano Zampini       if (vary[i]!=0 && vary[i]!=bs) {
12423a50541eSStefano Zampini         is_blocked = PETSC_FALSE;
12433a50541eSStefano Zampini         break;
12443a50541eSStefano Zampini       }
12453a50541eSStefano Zampini     }
12463a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
12473a50541eSStefano Zampini       vbs = bs;
12483a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
12493a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
12503a50541eSStefano Zampini       }
12513a50541eSStefano Zampini     }
12523a50541eSStefano Zampini     ierr = PetscFree(vary);CHKERRQ(ierr);
12533a50541eSStefano Zampini   }
12543a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
12553a50541eSStefano Zampini   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
1256a64d13efSStefano Zampini 
1257a64d13efSStefano Zampini   /* print some info if requested */
1258a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
1259a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1260a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
12610fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1262a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1263a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
12643a50541eSStefano 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);
1265a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
1266a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1267a64d13efSStefano Zampini   }
1268a64d13efSStefano Zampini 
1269a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
12703a50541eSStefano Zampini   ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1271854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
1272854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
1273a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
12744641a718SStefano Zampini   for (i=0; i<n_D; i++) {
12754641a718SStefano Zampini     ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
12764641a718SStefano Zampini   }
1277a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1278a64d13efSStefano Zampini   for (i=0, j=0; i<n_R; i++) {
12794641a718SStefano Zampini     if (!PetscBTLookup(bitmask,idx_R_local[i])) {
12804641a718SStefano Zampini       aux_array1[j++] = i;
1281a64d13efSStefano Zampini     }
1282a64d13efSStefano Zampini   }
1283a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1284a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1285a64d13efSStefano Zampini   for (i=0, j=0; i<n_B; i++) {
12864641a718SStefano Zampini     if (!PetscBTLookup(bitmask,is_indices[i])) {
12874641a718SStefano Zampini       aux_array2[j++] = i;
1288a64d13efSStefano Zampini     }
1289a64d13efSStefano Zampini   }
1290a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1291a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
1292a64d13efSStefano Zampini   ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1293a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1294a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1295a64d13efSStefano Zampini 
12968eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
1297785e854fSJed Brown     ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
1298a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
12994641a718SStefano Zampini       if (PetscBTLookup(bitmask,idx_R_local[i])) {
13004641a718SStefano Zampini         aux_array1[j++] = i;
1301a64d13efSStefano Zampini       }
1302a64d13efSStefano Zampini     }
1303a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1304a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1305a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1306a64d13efSStefano Zampini   }
13074641a718SStefano Zampini   ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
13083a50541eSStefano Zampini   ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1309a64d13efSStefano Zampini   PetscFunctionReturn(0);
1310a64d13efSStefano Zampini }
1311a64d13efSStefano Zampini 
1312304d26faSStefano Zampini 
1313304d26faSStefano Zampini #undef __FUNCT__
1314304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1315684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1316304d26faSStefano Zampini {
1317304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1318304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1319304d26faSStefano Zampini   PC             pc_temp;
1320304d26faSStefano Zampini   Mat            A_RR;
1321f4ddd8eeSStefano Zampini   MatReuse       reuse;
1322304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1323304d26faSStefano Zampini   PetscReal      value;
1324af732b37SStefano Zampini   PetscInt       n_D,n_R,ibs,mbs;
13259577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1326304d26faSStefano Zampini   PetscErrorCode ierr;
1327e604994aSStefano Zampini   /* prefixes stuff */
1328312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1329e604994aSStefano Zampini   size_t         len;
1330304d26faSStefano Zampini 
1331304d26faSStefano Zampini   PetscFunctionBegin;
1332304d26faSStefano Zampini 
1333e604994aSStefano Zampini   /* compute prefixes */
1334e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1335e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1336e604994aSStefano Zampini   if (!pcbddc->current_level) {
1337e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1338e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1339e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1340e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1341e604994aSStefano Zampini   } else {
1342e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1343312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1344e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1345e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1346312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1347312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
134834d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
134934d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1350e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1351e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1352e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1353e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1354e604994aSStefano Zampini   }
1355e604994aSStefano Zampini 
1356304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1357684f6988SStefano Zampini   if (dirichlet) {
1358ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
13598ce42a96SStefano Zampini     ierr = ISGetSize(pcis->is_I_local,&n_D);CHKERRQ(ierr);
1360304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1361304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1362304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1363304d26faSStefano Zampini       /* default */
1364304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1365e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
13669577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1367304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
13689577ea80SStefano Zampini       if (issbaij) {
13699577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
13709577ea80SStefano Zampini       } else {
1371304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13729577ea80SStefano Zampini       }
1373304d26faSStefano Zampini       /* Allow user's customization */
1374304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1375304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1376304d26faSStefano Zampini     }
1377d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1378304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1379304d26faSStefano Zampini     if (!n_D) {
1380304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1381304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1382304d26faSStefano Zampini     }
1383304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1384304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1385304d26faSStefano Zampini     /* set ksp_D into pcis data */
1386304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1387304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1388304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1389684f6988SStefano Zampini   }
1390304d26faSStefano Zampini 
1391304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1392684f6988SStefano Zampini   A_RR = 0;
1393684f6988SStefano Zampini   if (neumann) {
1394f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
13958ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1396f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1397f4ddd8eeSStefano Zampini       PetscInt nn_R;
139881d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1399f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1400f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1401f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1402f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1403f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1404f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1405f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1406727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1407f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1408f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1409f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1410f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1411f4ddd8eeSStefano Zampini         }
1412f4ddd8eeSStefano Zampini       }
1413f4ddd8eeSStefano Zampini       /* last check */
1414d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1415f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1416f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1417f4ddd8eeSStefano Zampini       }
1418f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1419f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1420f4ddd8eeSStefano Zampini     }
1421f4ddd8eeSStefano Zampini     /* extract A_RR */
1422af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1423af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
14243a50541eSStefano Zampini     if (ibs != mbs) {
1425af732b37SStefano Zampini       Mat newmat;
1426af732b37SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
1427f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1428af732b37SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
1429af732b37SStefano Zampini     } else {
1430f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1431af732b37SStefano Zampini     }
1432f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
1433304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1434304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1435304d26faSStefano Zampini       /* default */
1436304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1437e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
1438304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
14399577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
14409577ea80SStefano Zampini       if (issbaij) {
14419577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
14429577ea80SStefano Zampini       } else {
1443304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
14449577ea80SStefano Zampini       }
1445304d26faSStefano Zampini       /* Allow user's customization */
1446304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1447304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1448304d26faSStefano Zampini     }
1449d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
1450304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1451304d26faSStefano Zampini     if (!n_R) {
1452304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1453304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1454304d26faSStefano Zampini     }
1455304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
1456304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1457684f6988SStefano Zampini   }
1458304d26faSStefano Zampini 
1459304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
14600fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
1461684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
1462684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1463684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1464684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1465684f6988SStefano Zampini     }
1466684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
14670fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
14680fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
14690fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
14700fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
14710fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
1472304d26faSStefano Zampini       /* need to be adapted? */
1473b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1474b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1475b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
1476304d26faSStefano Zampini       /* print info */
1477304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1478e604994aSStefano 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);
1479304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1480304d26faSStefano Zampini       }
1481b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
14828ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);CHKERRQ(ierr);
1483304d26faSStefano Zampini       }
1484684f6988SStefano Zampini     }
1485684f6988SStefano Zampini     if (neumann) { /* Neumann */
14860fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
14870fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14880fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
14890fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
14900fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
1491304d26faSStefano Zampini       /* need to be adapted? */
1492b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1493b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1494304d26faSStefano Zampini       /* print info */
1495304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1496e604994aSStefano 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);
1497304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1498304d26faSStefano Zampini       }
1499b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
15008ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcbddc->is_R_local);CHKERRQ(ierr);
1501304d26faSStefano Zampini       }
15020fccc4e9SStefano Zampini     }
1503684f6988SStefano Zampini   }
1504304d26faSStefano Zampini   /* free Neumann problem's matrix */
1505304d26faSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1506304d26faSStefano Zampini   PetscFunctionReturn(0);
1507304d26faSStefano Zampini }
1508304d26faSStefano Zampini 
1509304d26faSStefano Zampini #undef __FUNCT__
1510ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
151120c7b377SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec rhs, Vec sol, Vec work, PetscBool applytranspose)
1512674ae819SStefano Zampini {
1513674ae819SStefano Zampini   PetscErrorCode ierr;
1514674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
1515674ae819SStefano Zampini 
1516674ae819SStefano Zampini   PetscFunctionBegin;
151720c7b377SStefano Zampini   if (applytranspose) {
1518674ae819SStefano Zampini     if (pcbddc->local_auxmat1) {
151920c7b377SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,rhs,work);CHKERRQ(ierr);
152020c7b377SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,work,rhs,rhs);CHKERRQ(ierr);
152120c7b377SStefano Zampini     }
152220c7b377SStefano Zampini     ierr = KSPSolveTranspose(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
152320c7b377SStefano Zampini   } else {
152420c7b377SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
152520c7b377SStefano Zampini     if (pcbddc->local_auxmat1) {
152620c7b377SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,sol,work);CHKERRQ(ierr);
152720c7b377SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,work,sol,sol);CHKERRQ(ierr);
152820c7b377SStefano Zampini     }
1529674ae819SStefano Zampini   }
1530674ae819SStefano Zampini   PetscFunctionReturn(0);
1531674ae819SStefano Zampini }
1532674ae819SStefano Zampini 
1533dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
1534674ae819SStefano Zampini #undef __FUNCT__
1535674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
1536dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
1537674ae819SStefano Zampini {
1538674ae819SStefano Zampini   PetscErrorCode ierr;
1539674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1540674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
1541674ae819SStefano Zampini   const PetscScalar zero = 0.0;
1542674ae819SStefano Zampini 
1543674ae819SStefano Zampini   PetscFunctionBegin;
1544dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
1545dc359a40SStefano Zampini   if (applytranspose) {
1546674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
15478eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
1548dc359a40SStefano Zampini   } else {
1549674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
1550674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
155115aaf578SStefano Zampini   }
155212edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
155312edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
155412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155612edc857SStefano Zampini 
15579f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
155812edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
155912edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
156012edc857SStefano Zampini     if (applytranspose) {
156112edc857SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
156212edc857SStefano Zampini     } else {
156312edc857SStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
156412edc857SStefano Zampini     }
156512edc857SStefano Zampini   }
1566674ae819SStefano Zampini 
1567674ae819SStefano Zampini   /* Local solution on R nodes */
15689f00e9b4SStefano Zampini   if (pcis->n) {
1569674ae819SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
1570674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1571674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15728eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1573674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1574674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1575674ae819SStefano Zampini     }
157620c7b377SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcbddc->vec1_R,pcbddc->vec2_R,pcbddc->vec1_C,applytranspose);CHKERRQ(ierr);
1577674ae819SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1578674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1579674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15808eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1581674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1582674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1583674ae819SStefano Zampini     }
15849f00e9b4SStefano Zampini   }
1585674ae819SStefano Zampini 
15869f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
15879f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
158812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1589674ae819SStefano Zampini 
1590674ae819SStefano Zampini   /* Sum contributions from two levels */
1591dc359a40SStefano Zampini   if (applytranspose) {
1592dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
1593dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1594dc359a40SStefano Zampini   } else {
1595674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
15968eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1597dc359a40SStefano Zampini   }
1598674ae819SStefano Zampini   PetscFunctionReturn(0);
1599674ae819SStefano Zampini }
1600674ae819SStefano Zampini 
160112edc857SStefano Zampini /* TODO: the following two function can be optimized using VecPlaceArray whenever possible and using overlap flag */
1602674ae819SStefano Zampini #undef __FUNCT__
1603674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
160412edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
1605674ae819SStefano Zampini {
1606674ae819SStefano Zampini   PetscErrorCode ierr;
1607674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
160812edc857SStefano Zampini   PetscScalar    *array,*array2;
160912edc857SStefano Zampini   Vec            from,to;
1610674ae819SStefano Zampini 
1611674ae819SStefano Zampini   PetscFunctionBegin;
161212edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
161312edc857SStefano Zampini     from = pcbddc->coarse_vec;
161412edc857SStefano Zampini     to = pcbddc->vec1_P;
161512edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
161612edc857SStefano Zampini       Vec tvec;
161712edc857SStefano Zampini       PetscInt lsize;
161812edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
161912edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
162012edc857SStefano Zampini       ierr = VecGetArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
162112edc857SStefano Zampini       ierr = VecGetArray(from,&array2);CHKERRQ(ierr);
162212edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
162312edc857SStefano Zampini       ierr = VecRestoreArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
162412edc857SStefano Zampini       ierr = VecRestoreArray(from,&array2);CHKERRQ(ierr);
162512edc857SStefano Zampini     }
162612edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
162712edc857SStefano Zampini     from = pcbddc->vec1_P;
162812edc857SStefano Zampini     to = pcbddc->coarse_vec;
162912edc857SStefano Zampini   }
163012edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
1631674ae819SStefano Zampini   PetscFunctionReturn(0);
1632674ae819SStefano Zampini }
1633674ae819SStefano Zampini 
1634674ae819SStefano Zampini #undef __FUNCT__
1635674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
163612edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
1637674ae819SStefano Zampini {
1638674ae819SStefano Zampini   PetscErrorCode ierr;
1639674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
164012edc857SStefano Zampini   PetscScalar    *array,*array2;
164112edc857SStefano Zampini   Vec            from,to;
1642674ae819SStefano Zampini 
1643674ae819SStefano Zampini   PetscFunctionBegin;
164412edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
164512edc857SStefano Zampini     from = pcbddc->coarse_vec;
164612edc857SStefano Zampini     to = pcbddc->vec1_P;
164712edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
164812edc857SStefano Zampini     from = pcbddc->vec1_P;
164912edc857SStefano Zampini     to = pcbddc->coarse_vec;
165012edc857SStefano Zampini   }
165112edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
165212edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
165312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
165412edc857SStefano Zampini       Vec tvec;
165512edc857SStefano Zampini       PetscInt lsize;
165612edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
165712edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
165812edc857SStefano Zampini       ierr = VecGetArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
165912edc857SStefano Zampini       ierr = VecGetArray(tvec,&array2);CHKERRQ(ierr);
166012edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
166112edc857SStefano Zampini       ierr = VecRestoreArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
166212edc857SStefano Zampini       ierr = VecRestoreArray(tvec,&array2);CHKERRQ(ierr);
166312edc857SStefano Zampini     }
166412edc857SStefano Zampini   }
1665674ae819SStefano Zampini   PetscFunctionReturn(0);
1666674ae819SStefano Zampini }
1667674ae819SStefano Zampini 
1668984c4197SStefano Zampini /* uncomment for testing purposes */
1669984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
1670674ae819SStefano Zampini #undef __FUNCT__
1671674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
1672674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
1673674ae819SStefano Zampini {
1674674ae819SStefano Zampini   PetscErrorCode    ierr;
1675674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
1676674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1677674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
1678984c4197SStefano Zampini   /* constraint and (optionally) change of basis matrix implemented as SeqAIJ */
1679674ae819SStefano Zampini   MatType           impMatType=MATSEQAIJ;
1680984c4197SStefano Zampini   /* one and zero */
1681984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
1682984c4197SStefano Zampini   /* space to store constraints and their local indices */
1683984c4197SStefano Zampini   PetscScalar       *temp_quadrature_constraint;
1684984c4197SStefano Zampini   PetscInt          *temp_indices,*temp_indices_to_constraint,*temp_indices_to_constraint_B;
1685984c4197SStefano Zampini   /* iterators */
1686984c4197SStefano Zampini   PetscInt          i,j,k,total_counts,temp_start_ptr;
1687984c4197SStefano Zampini   /* stuff to store connected components stored in pcbddc->mat_graph */
1688984c4197SStefano Zampini   IS                ISForVertices,*ISForFaces,*ISForEdges,*used_IS;
1689984c4197SStefano Zampini   PetscInt          n_ISForFaces,n_ISForEdges;
1690984c4197SStefano Zampini   /* near null space stuff */
1691674ae819SStefano Zampini   MatNullSpace      nearnullsp;
1692674ae819SStefano Zampini   const Vec         *nearnullvecs;
1693674ae819SStefano Zampini   Vec               *localnearnullsp;
1694984c4197SStefano Zampini   PetscBool         nnsp_has_cnst;
1695984c4197SStefano Zampini   PetscInt          nnsp_size;
1696984c4197SStefano Zampini   PetscScalar       *array;
1697984c4197SStefano Zampini   /* BLAS integers */
1698e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
1699e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
1700c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
1701984c4197SStefano Zampini   /* LAPACK working arrays for SVD or POD */
1702242a89d7SStefano Zampini   PetscBool         skip_lapack;
1703984c4197SStefano Zampini   PetscScalar       *work;
1704984c4197SStefano Zampini   PetscReal         *singular_vals;
1705984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1706984c4197SStefano Zampini   PetscReal         *rwork;
1707674ae819SStefano Zampini #endif
1708984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1709e310c8b4SStefano Zampini   PetscBLASInt      Blas_one_2=1;
1710984c4197SStefano Zampini   PetscScalar       *temp_basis,*correlation_mat;
1711b7d8b9f8SStefano Zampini #else
1712b7d8b9f8SStefano Zampini   PetscBLASInt      dummy_int_1=1,dummy_int_2=1;
1713b7d8b9f8SStefano Zampini   PetscScalar       dummy_scalar_1=0.0,dummy_scalar_2=0.0;
1714984c4197SStefano Zampini #endif
1715727cdba6SStefano Zampini   /* reuse */
1716727cdba6SStefano Zampini   PetscInt          olocal_primal_size;
1717727cdba6SStefano Zampini   PetscInt          *oprimal_indices_local_idxs;
1718984c4197SStefano Zampini   /* change of basis */
1719984c4197SStefano Zampini   PetscInt          *aux_primal_numbering,*aux_primal_minloc,*global_indices;
1720a717540cSStefano Zampini   PetscBool         boolforchange,qr_needed;
1721a717540cSStefano Zampini   PetscBT           touched,change_basis,qr_needed_idx;
1722984c4197SStefano Zampini   /* auxiliary stuff */
172339e2fb2aSStefano Zampini   PetscInt          *nnz,*is_indices,*aux_primal_numbering_B;
1724911cabfeSStefano Zampini   PetscInt          ncc,*gidxs,*permutation,*temp_indices_to_constraint_work;
1725911cabfeSStefano Zampini   PetscScalar       *temp_quadrature_constraint_work;
1726984c4197SStefano Zampini   /* some quantities */
172745a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
1728984c4197SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint,max_constraints,temp_constraints;
1729984c4197SStefano Zampini 
1730674ae819SStefano Zampini 
1731674ae819SStefano Zampini   PetscFunctionBegin;
17328e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
17338e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
17348e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
173508122e43SStefano Zampini   /* TODO synch with adaptive selection */
1736674ae819SStefano Zampini   /* Get index sets for faces, edges and vertices from graph */
1737d06fc5fdSStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
1738d06fc5fdSStefano Zampini   /* free unneeded index sets */
1739d06fc5fdSStefano Zampini   if (!pcbddc->use_vertices) {
1740d06fc5fdSStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
1741674ae819SStefano Zampini   }
1742d06fc5fdSStefano Zampini   if (!pcbddc->use_edges) {
1743d06fc5fdSStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
1744d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1745d06fc5fdSStefano Zampini     }
1746d06fc5fdSStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1747d06fc5fdSStefano Zampini     n_ISForEdges = 0;
1748d06fc5fdSStefano Zampini   }
1749d06fc5fdSStefano Zampini   if (!pcbddc->use_faces) {
1750d06fc5fdSStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
1751d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1752d06fc5fdSStefano Zampini     }
1753d06fc5fdSStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1754d06fc5fdSStefano Zampini     n_ISForFaces = 0;
1755d06fc5fdSStefano Zampini   }
1756d06fc5fdSStefano Zampini   /* HACKS (the following two blocks of code) */
1757b9b85e73SStefano Zampini   if (!ISForVertices && pcbddc->NullSpace && !pcbddc->user_ChangeOfBasisMatrix) {
1758b8ffe317SStefano Zampini     pcbddc->use_change_of_basis = PETSC_TRUE;
1759d06fc5fdSStefano Zampini     if (!ISForEdges) {
1760d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = PETSC_TRUE;
1761d06fc5fdSStefano Zampini     }
1762b8ffe317SStefano Zampini   }
176398a51de6SStefano Zampini   if (pcbddc->NullSpace) {
176498a51de6SStefano Zampini     /* use_change_of_basis should be consistent among processors */
1765d06fc5fdSStefano Zampini     PetscBool tbool[2],gbool[2];
1766d06fc5fdSStefano Zampini     tbool [0] = pcbddc->use_change_of_basis;
1767d06fc5fdSStefano Zampini     tbool [1] = pcbddc->use_change_on_faces;
1768d06fc5fdSStefano Zampini     ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1769d06fc5fdSStefano Zampini     pcbddc->use_change_of_basis = gbool[0];
1770d06fc5fdSStefano Zampini     pcbddc->use_change_on_faces = gbool[1];
177198a51de6SStefano Zampini   }
1772984c4197SStefano Zampini   /* print some info */
1773674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
17740fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1775674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
1776674ae819SStefano Zampini     i = 0;
1777674ae819SStefano Zampini     if (ISForVertices) {
1778674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&i);CHKERRQ(ierr);
1779674ae819SStefano Zampini     }
1780674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices\n",PetscGlobalRank,i);CHKERRQ(ierr);
1781674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges\n",PetscGlobalRank,n_ISForEdges);CHKERRQ(ierr);
178215aaf578SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces\n",PetscGlobalRank,n_ISForFaces);CHKERRQ(ierr);
1783674ae819SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1784674ae819SStefano Zampini   }
178508122e43SStefano Zampini 
178608122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
1787674ae819SStefano Zampini     /* check if near null space is attached to global mat */
1788674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
1789674ae819SStefano Zampini     if (nearnullsp) {
1790674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1791f4ddd8eeSStefano Zampini       /* remove any stored info */
1792f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1793f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1794f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
1795f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
1796f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
1797473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1798f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
1799f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
1800f4ddd8eeSStefano Zampini       }
1801984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
1802984c4197SStefano Zampini       nnsp_size = 0;
1803674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
1804674ae819SStefano Zampini     }
1805984c4197SStefano Zampini     /* get max number of constraints on a single cc */
1806984c4197SStefano Zampini     max_constraints = nnsp_size;
1807984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
1808984c4197SStefano Zampini 
1809674ae819SStefano Zampini     /*
1810674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
1811674ae819SStefano Zampini          - temp_indices will contain start index of each constraint stored as follows
1812911cabfeSStefano Zampini          - temp_indices_to_constraint  [temp_indices[i],...,temp_indices[i+1]-1] will contain the indices (in local numbering) on which the constraint acts
1813911cabfeSStefano Zampini          - temp_indices_to_constraint_B[temp_indices[i],...,temp_indices[i+1]-1] will contain the indices (in boundary numbering) on which the constraint acts
1814911cabfeSStefano Zampini          - temp_quadrature_constraint  [temp_indices[i],...,temp_indices[i+1]-1] will contain the scalars representing the constraint itself
1815674ae819SStefano Zampini                                                                                                                                                            */
1816674ae819SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
1817984c4197SStefano Zampini     total_counts *= max_constraints;
1818674ae819SStefano Zampini     n_vertices = 0;
1819674ae819SStefano Zampini     if (ISForVertices) {
1820674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
1821674ae819SStefano Zampini     }
1822674ae819SStefano Zampini     total_counts += n_vertices;
1823854ce69bSBarry Smith     ierr = PetscMalloc1(total_counts+1,&temp_indices);CHKERRQ(ierr);
18244641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
1825674ae819SStefano Zampini     total_counts = 0;
1826674ae819SStefano Zampini     max_size_of_constraint = 0;
1827674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
1828674ae819SStefano Zampini       if (i<n_ISForEdges) {
1829674ae819SStefano Zampini         used_IS = &ISForEdges[i];
1830674ae819SStefano Zampini       } else {
1831674ae819SStefano Zampini         used_IS = &ISForFaces[i-n_ISForEdges];
1832674ae819SStefano Zampini       }
1833674ae819SStefano Zampini       ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
1834674ae819SStefano Zampini       total_counts += j;
1835674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
1836674ae819SStefano Zampini     }
1837984c4197SStefano Zampini     total_counts *= max_constraints;
1838674ae819SStefano Zampini     total_counts += n_vertices;
1839906d46d4SStefano Zampini     ierr = PetscMalloc3(total_counts,&temp_quadrature_constraint,total_counts,&temp_indices_to_constraint,total_counts,&temp_indices_to_constraint_B);CHKERRQ(ierr);
1840984c4197SStefano Zampini     /* get local part of global near null space vectors */
1841785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
1842984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
1843984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
1844984c4197SStefano Zampini       ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1845984c4197SStefano Zampini       ierr = VecScatterEnd(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1846984c4197SStefano Zampini     }
1847674ae819SStefano Zampini 
1848242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
1849242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
1850a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
1851242a89d7SStefano Zampini 
18528f1c130eSStefano Zampini     /* allocate some auxiliary stuff */
18538f1c130eSStefano Zampini     if (!skip_lapack || pcbddc->use_qr_single) {
18548f1c130eSStefano Zampini       ierr = PetscMalloc4(max_size_of_constraint,&gidxs,max_size_of_constraint,&permutation,max_size_of_constraint,&temp_indices_to_constraint_work,max_size_of_constraint,&temp_quadrature_constraint_work);CHKERRQ(ierr);
18558f1c130eSStefano Zampini     }
18568f1c130eSStefano Zampini 
1857984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
1858a773dcb8SStefano Zampini     if (!skip_lapack) {
1859674ae819SStefano Zampini       PetscScalar temp_work;
1860911cabfeSStefano Zampini 
1861674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1862984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
1863785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
1864785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
1865785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
1866674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1867785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
1868674ae819SStefano Zampini #endif
1869674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
1870c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
1871c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
1872674ae819SStefano Zampini       lwork = -1;
1873674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1874674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1875c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
1876674ae819SStefano Zampini #else
1877c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
1878674ae819SStefano Zampini #endif
1879674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
1880984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
1881674ae819SStefano Zampini #else /* on missing GESVD */
1882674ae819SStefano Zampini       /* SVD */
1883674ae819SStefano Zampini       PetscInt max_n,min_n;
1884674ae819SStefano Zampini       max_n = max_size_of_constraint;
1885984c4197SStefano Zampini       min_n = max_constraints;
1886984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
1887674ae819SStefano Zampini         min_n = max_size_of_constraint;
1888984c4197SStefano Zampini         max_n = max_constraints;
1889674ae819SStefano Zampini       }
1890785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
1891674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1892785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
1893674ae819SStefano Zampini #endif
1894674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
1895674ae819SStefano Zampini       lwork = -1;
1896e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
1897e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
1898b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
1899674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1900674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1901e310c8b4SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&temp_quadrature_constraint[0],&Blas_LDA,singular_vals,&dummy_scalar_1,&dummy_int_1,&dummy_scalar_2,&dummy_int_2,&temp_work,&lwork,&lierr));
1902674ae819SStefano Zampini #else
1903e310c8b4SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&temp_quadrature_constraint[0],&Blas_LDA,singular_vals,&dummy_scalar_1,&dummy_int_1,&dummy_scalar_2,&dummy_int_2,&temp_work,&lwork,rwork,&lierr));
1904674ae819SStefano Zampini #endif
1905674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
1906984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
1907984c4197SStefano Zampini #endif /* on missing GESVD */
1908674ae819SStefano Zampini       /* Allocate optimal workspace */
1909674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
1910854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
1911674ae819SStefano Zampini     }
1912674ae819SStefano Zampini     /* Now we can loop on constraining sets */
1913674ae819SStefano Zampini     total_counts = 0;
1914674ae819SStefano Zampini     temp_indices[0] = 0;
1915674ae819SStefano Zampini     /* vertices */
1916674ae819SStefano Zampini     if (ISForVertices) {
1917674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1918674ae819SStefano Zampini       if (nnsp_has_cnst) { /* consider all vertices */
191939e2fb2aSStefano Zampini         ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
1920674ae819SStefano Zampini         for (i=0;i<n_vertices;i++) {
1921674ae819SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1922674ae819SStefano Zampini           temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1923674ae819SStefano Zampini           total_counts++;
1924674ae819SStefano Zampini         }
1925674ae819SStefano Zampini       } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
1926984c4197SStefano Zampini         PetscBool used_vertex;
1927674ae819SStefano Zampini         for (i=0;i<n_vertices;i++) {
1928674ae819SStefano Zampini           used_vertex = PETSC_FALSE;
1929674ae819SStefano Zampini           k = 0;
1930674ae819SStefano Zampini           while (!used_vertex && k<nnsp_size) {
1931984c4197SStefano Zampini             ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1932984c4197SStefano Zampini             if (PetscAbsScalar(array[is_indices[i]])>0.0) {
1933674ae819SStefano Zampini               temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1934674ae819SStefano Zampini               temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1935674ae819SStefano Zampini               temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1936674ae819SStefano Zampini               total_counts++;
1937674ae819SStefano Zampini               used_vertex = PETSC_TRUE;
1938674ae819SStefano Zampini             }
1939984c4197SStefano Zampini             ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1940674ae819SStefano Zampini             k++;
1941674ae819SStefano Zampini           }
1942674ae819SStefano Zampini         }
1943674ae819SStefano Zampini       }
1944674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1945674ae819SStefano Zampini       n_vertices = total_counts;
1946674ae819SStefano Zampini     }
1947984c4197SStefano Zampini 
1948674ae819SStefano Zampini     /* edges and faces */
1949911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
1950911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
1951911cabfeSStefano Zampini         used_IS = &ISForEdges[ncc];
1952984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
1953674ae819SStefano Zampini       } else {
1954911cabfeSStefano Zampini         used_IS = &ISForFaces[ncc-n_ISForEdges];
1955984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
1956674ae819SStefano Zampini       }
1957674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
1958674ae819SStefano Zampini       temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
1959674ae819SStefano Zampini       ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
1960674ae819SStefano Zampini       ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1961984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
1962984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
1963674ae819SStefano Zampini       if (nnsp_has_cnst) {
19645b08dc53SStefano Zampini         PetscScalar quad_value;
1965674ae819SStefano Zampini         temp_constraints++;
1966a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
1967674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
1968a773dcb8SStefano Zampini         } else {
1969a773dcb8SStefano Zampini           quad_value = 1.0;
1970a773dcb8SStefano Zampini         }
197139e2fb2aSStefano Zampini         ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1972674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
1973674ae819SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
1974674ae819SStefano Zampini         }
197508122e43SStefano Zampini         /* sort by global ordering if using lapack subroutines (not needed!) */
19768f1c130eSStefano Zampini         if (!skip_lapack || pcbddc->use_qr_single) {
1977911cabfeSStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
1978911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1979911cabfeSStefano Zampini             permutation[j]=j;
1980911cabfeSStefano Zampini           }
1981911cabfeSStefano Zampini           ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
1982911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
198308122e43SStefano Zampini             if (permutation[j]!=j) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"This should not happen");
198408122e43SStefano Zampini           }
198508122e43SStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1986911cabfeSStefano Zampini             temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
1987911cabfeSStefano Zampini             temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
1988911cabfeSStefano Zampini           }
1989911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1990911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
1991911cabfeSStefano Zampini         }
1992674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
1993674ae819SStefano Zampini         total_counts++;
1994674ae819SStefano Zampini       }
1995674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
1996984c4197SStefano Zampini         PetscReal real_value;
1997984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
199839e2fb2aSStefano Zampini         ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1999674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
2000984c4197SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]+j]=array[is_indices[j]];
2001674ae819SStefano Zampini         }
2002984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2003984c4197SStefano Zampini         /* check if array is null on the connected component */
2004e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2005e310c8b4SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,&temp_quadrature_constraint[temp_indices[total_counts]],&Blas_one));
20065b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2007911cabfeSStefano Zampini           /* sort by global ordering if using lapack subroutines */
20088f1c130eSStefano Zampini           if (!skip_lapack || pcbddc->use_qr_single) {
2009911cabfeSStefano Zampini             ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
2010911cabfeSStefano Zampini             for (j=0;j<size_of_constraint;j++) {
2011911cabfeSStefano Zampini               permutation[j]=j;
2012911cabfeSStefano Zampini             }
2013911cabfeSStefano Zampini             ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
2014911cabfeSStefano Zampini             for (j=0;j<size_of_constraint;j++) {
2015911cabfeSStefano Zampini               temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
2016911cabfeSStefano Zampini               temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
2017911cabfeSStefano Zampini             }
2018911cabfeSStefano Zampini             ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
2019911cabfeSStefano Zampini             ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
2020911cabfeSStefano Zampini           }
2021674ae819SStefano Zampini           temp_constraints++;
2022674ae819SStefano Zampini           temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
2023674ae819SStefano Zampini           total_counts++;
2024674ae819SStefano Zampini         }
2025674ae819SStefano Zampini       }
2026674ae819SStefano Zampini       ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
202745a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2028eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2029a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
2030a773dcb8SStefano Zampini           PetscScalar norm;
2031a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2032a773dcb8SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one));
2033a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
2034a773dcb8SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one));
2035a773dcb8SStefano Zampini         } else { /* perform SVD */
2036984c4197SStefano Zampini           PetscReal tol = 1.0e-8; /* tolerance for retaining eigenmodes */
2037674ae819SStefano Zampini 
2038674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2039984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
2040984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
2041984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
2042984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
2043984c4197SStefano Zampini                 from that computed using LAPACKgesvd
2044984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
2045984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
2046984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
2047674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
2048e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2049984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2050674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
2051674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
2052e310c8b4SStefano Zampini               PetscStackCallBLAS("BLASdot",correlation_mat[j*temp_constraints+k]=BLASdot_(&Blas_N,&temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Blas_one,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Blas_one_2));
2053674ae819SStefano Zampini             }
2054674ae819SStefano Zampini           }
2055e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
2056e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2057e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
2058674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2059c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
2060674ae819SStefano Zampini #else
2061c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
2062674ae819SStefano Zampini #endif
2063674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2064984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
2065984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
2066674ae819SStefano Zampini           j = 0;
2067984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
2068674ae819SStefano Zampini           total_counts = total_counts-j;
206945a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
2070e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
2071c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2072c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2073c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
2074c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2075c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
2076c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2077674ae819SStefano Zampini           if (j<temp_constraints) {
2078984c4197SStefano Zampini             PetscInt ii;
2079984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]);
2080674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2081c4303822SStefano Zampini             PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Blas_LDA,correlation_mat,&Blas_LDB,&zero,temp_basis,&Blas_LDC));
2082674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2083984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
2084674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
2085984c4197SStefano Zampini                 temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii]=singular_vals[temp_constraints-1-k]*temp_basis[(temp_constraints-1-k)*size_of_constraint+ii];
2086674ae819SStefano Zampini               }
2087674ae819SStefano Zampini             }
2088674ae819SStefano Zampini           }
2089674ae819SStefano Zampini #else  /* on missing GESVD */
2090e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2091e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2092b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2093674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2094674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2095e310c8b4SStefano Zampini           PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Blas_LDA,singular_vals,&dummy_scalar_1,&dummy_int_1,&dummy_scalar_2,&dummy_int_2,work,&lwork,&lierr));
2096674ae819SStefano Zampini #else
2097e310c8b4SStefano Zampini           PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Blas_LDA,singular_vals,&dummy_scalar_1,&dummy_int_1,&dummy_scalar_2,&dummy_int_2,work,&lwork,rwork,&lierr));
2098674ae819SStefano Zampini #endif
2099984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
2100674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2101984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
2102e310c8b4SStefano Zampini           k = temp_constraints;
2103e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
2104674ae819SStefano Zampini           j = 0;
2105e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
210645a1bb75SStefano Zampini           valid_constraints = k-j;
2107911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
2108984c4197SStefano Zampini #endif /* on missing GESVD */
2109674ae819SStefano Zampini         }
2110a773dcb8SStefano Zampini       }
211145a1bb75SStefano Zampini       /* setting change_of_basis flag is safe now */
211245a1bb75SStefano Zampini       if (boolforchange) {
211345a1bb75SStefano Zampini         for (j=0;j<valid_constraints;j++) {
211445a1bb75SStefano Zampini           PetscBTSet(change_basis,total_counts-j-1);
211545a1bb75SStefano Zampini         }
211645a1bb75SStefano Zampini       }
2117674ae819SStefano Zampini     }
2118984c4197SStefano Zampini     /* free workspace */
21198f1c130eSStefano Zampini     if (!skip_lapack || pcbddc->use_qr_single) {
2120911cabfeSStefano Zampini       ierr = PetscFree4(gidxs,permutation,temp_indices_to_constraint_work,temp_quadrature_constraint_work);CHKERRQ(ierr);
21218f1c130eSStefano Zampini     }
21228f1c130eSStefano Zampini     if (!skip_lapack) {
2123984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
2124984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2125984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
2126984c4197SStefano Zampini #endif
2127984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
2128984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2129984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
2130984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2131984c4197SStefano Zampini #endif
2132984c4197SStefano Zampini     }
2133984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2134984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
2135984c4197SStefano Zampini     }
2136984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
213708122e43SStefano Zampini   } else {
213808122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
213908122e43SStefano Zampini     PetscInt        cum = 0;
214008122e43SStefano Zampini 
214108122e43SStefano Zampini     total_counts = 0;
214208122e43SStefano Zampini     n_vertices = 0;
214308122e43SStefano Zampini     if (sub_schurs->is_Ej_com) {
214408122e43SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_Ej_com,&n_vertices);CHKERRQ(ierr);
214508122e43SStefano Zampini     }
214608122e43SStefano Zampini     max_constraints = 0;
214708122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
214808122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
214908122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
215008122e43SStefano Zampini     }
215108122e43SStefano Zampini     temp_indices = pcbddc->adaptive_constraints_ptrs;
215208122e43SStefano Zampini     temp_indices_to_constraint = pcbddc->adaptive_constraints_idxs;
215308122e43SStefano Zampini     temp_quadrature_constraint = pcbddc->adaptive_constraints_data;
215408122e43SStefano Zampini 
215508122e43SStefano Zampini #if 0
215608122e43SStefano Zampini     printf("Found %d totals\n",total_counts);
215708122e43SStefano Zampini     for (i=0;i<total_counts;i++) {
215808122e43SStefano Zampini       printf("const %d, start %d",i,temp_indices[i]);
215908122e43SStefano Zampini       printf(" end %d:\n",temp_indices[i+1]);
216008122e43SStefano Zampini       for (j=temp_indices[i];j<temp_indices[i+1];j++) {
216108122e43SStefano Zampini         printf("  idxs %d",temp_indices_to_constraint[j]);
216208122e43SStefano Zampini         printf("  data %1.2e\n",temp_quadrature_constraint[j]);
216308122e43SStefano Zampini       }
216408122e43SStefano Zampini     }
216508122e43SStefano Zampini #endif
216608122e43SStefano Zampini 
216708122e43SStefano Zampini     for (i=0;i<total_counts;i++) max_size_of_constraint = PetscMax(max_size_of_constraint,temp_indices[i+1]-temp_indices[i]);
216808122e43SStefano Zampini     ierr = PetscMalloc1(temp_indices[total_counts],&temp_indices_to_constraint_B);CHKERRQ(ierr);
216908122e43SStefano Zampini     /* Change of basis */
217008122e43SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
217108122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
2172*bbb9e6c6SStefano Zampini       cum = n_vertices;
217308122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
217408122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
2175*bbb9e6c6SStefano Zampini           for (j=0;j<pcbddc->adaptive_constraints_n[i+n_vertices];j++) {
217608122e43SStefano Zampini             ierr = PetscBTSet(change_basis,cum+j);CHKERRQ(ierr);
217708122e43SStefano Zampini           }
217808122e43SStefano Zampini         }
2179*bbb9e6c6SStefano Zampini         cum += pcbddc->adaptive_constraints_n[i+n_vertices];
218008122e43SStefano Zampini       }
218108122e43SStefano Zampini     }
218208122e43SStefano Zampini   }
218308122e43SStefano Zampini 
218408122e43SStefano Zampini   /* free index sets of faces, edges and vertices */
218508122e43SStefano Zampini   for (i=0;i<n_ISForFaces;i++) {
218608122e43SStefano Zampini     ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
218708122e43SStefano Zampini   }
218808122e43SStefano Zampini   if (n_ISForFaces) {
218908122e43SStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
219008122e43SStefano Zampini   }
219108122e43SStefano Zampini   for (i=0;i<n_ISForEdges;i++) {
219208122e43SStefano Zampini     ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
219308122e43SStefano Zampini   }
219408122e43SStefano Zampini   if (n_ISForEdges) {
219508122e43SStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
219608122e43SStefano Zampini   }
219708122e43SStefano Zampini   ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
219808122e43SStefano Zampini 
219908122e43SStefano Zampini   /* map temp_indices_to_constraint in boundary numbering */
220008122e43SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,temp_indices[total_counts],temp_indices_to_constraint,&i,temp_indices_to_constraint_B);CHKERRQ(ierr);
220108122e43SStefano Zampini   if (i != temp_indices[total_counts]) {
220208122e43SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",temp_indices[total_counts],i);
220308122e43SStefano Zampini   }
2204984c4197SStefano Zampini 
2205727cdba6SStefano Zampini   /* set quantities in pcbddc data structure and store previous primal size */
2206984c4197SStefano Zampini   /* n_vertices defines the number of subdomain corners in the primal space */
2207674ae819SStefano Zampini   /* n_constraints defines the number of averages (they can be point primal dofs if change of basis is requested) */
2208727cdba6SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
2209984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
2210674ae819SStefano Zampini   pcbddc->n_vertices = n_vertices;
2211984c4197SStefano Zampini   pcbddc->n_constraints = pcbddc->local_primal_size-pcbddc->n_vertices;
2212674ae819SStefano Zampini 
2213674ae819SStefano Zampini   /* Create constraint matrix */
2214674ae819SStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
2215674ae819SStefano Zampini   /* so we need to set it up properly either with or without change of basis */
2216674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2217674ae819SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
2218984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
2219984c4197SStefano Zampini   /* array to compute a local numbering of constraints : vertices first then constraints */
2220785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_numbering);CHKERRQ(ierr);
2221984c4197SStefano Zampini   /* array to select the proper local node (of minimum index with respect to global ordering) when changing the basis */
2222984c4197SStefano Zampini   /* note: it should not be needed since IS for faces and edges are already sorted by global ordering when analyzing the graph but... just in case */
2223785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_minloc);CHKERRQ(ierr);
2224984c4197SStefano Zampini   /* auxiliary stuff for basis change */
2225785e854fSJed Brown   ierr = PetscMalloc1(max_size_of_constraint,&global_indices);CHKERRQ(ierr);
22264641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n_B,&touched);CHKERRQ(ierr);
2227984c4197SStefano Zampini 
2228984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
2229984c4197SStefano Zampini   total_primal_vertices=0;
2230984c4197SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
2231674ae819SStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
2232984c4197SStefano Zampini     if (size_of_constraint == 1) {
22334641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]]);CHKERRQ(ierr);
2234984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]];
2235984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=0;
2236984c4197SStefano Zampini       total_primal_vertices++;
22374641a718SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) { /* Same procedure used in PCBDDCGetPrimalConstraintsLocalIdx */
2238984c4197SStefano Zampini       PetscInt min_loc,min_index;
2239984c4197SStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],global_indices);CHKERRQ(ierr);
2240984c4197SStefano Zampini       /* find first untouched local node */
2241674ae819SStefano Zampini       k = 0;
22424641a718SStefano Zampini       while (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) k++;
2243984c4197SStefano Zampini       min_index = global_indices[k];
2244984c4197SStefano Zampini       min_loc = k;
2245984c4197SStefano Zampini       /* search the minimum among global nodes already untouched on the cc */
2246984c4197SStefano Zampini       for (k=1;k<size_of_constraint;k++) {
2247984c4197SStefano Zampini         /* there can be more than one constraint on a single connected component */
22484641a718SStefano Zampini         if (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k]) && min_index > global_indices[k]) {
2249984c4197SStefano Zampini           min_index = global_indices[k];
2250984c4197SStefano Zampini           min_loc = k;
2251674ae819SStefano Zampini         }
2252674ae819SStefano Zampini       }
22534641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]+min_loc]);CHKERRQ(ierr);
2254984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]+min_loc];
2255984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=min_loc;
2256984c4197SStefano Zampini       total_primal_vertices++;
2257984c4197SStefano Zampini     }
2258984c4197SStefano Zampini   }
2259a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
2260a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
2261a717540cSStefano Zampini   ierr = PetscBTCreate(pcbddc->local_primal_size,&qr_needed_idx);CHKERRQ(ierr);
2262a717540cSStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2263a717540cSStefano Zampini     if (PetscBTLookup(change_basis,i)) {
2264fa434743SStefano Zampini       if (!pcbddc->use_qr_single) {
2265a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2266a717540cSStefano Zampini         j = 0;
2267a717540cSStefano Zampini         for (k=0;k<size_of_constraint;k++) {
2268a717540cSStefano Zampini           if (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) {
2269a717540cSStefano Zampini             j++;
2270a717540cSStefano Zampini           }
2271a717540cSStefano Zampini         }
2272a717540cSStefano Zampini         /* found more than one primal dof on the cc */
2273a717540cSStefano Zampini         if (j > 1) {
2274a717540cSStefano Zampini           PetscBTSet(qr_needed_idx,i);
2275a717540cSStefano Zampini           qr_needed = PETSC_TRUE;
2276a717540cSStefano Zampini         }
2277fa434743SStefano Zampini       } else {
2278fa434743SStefano Zampini         PetscBTSet(qr_needed_idx,i);
2279fa434743SStefano Zampini         qr_needed = PETSC_TRUE;
2280fa434743SStefano Zampini       }
2281a717540cSStefano Zampini     }
2282a717540cSStefano Zampini   }
2283984c4197SStefano Zampini   /* free workspace */
2284984c4197SStefano Zampini   ierr = PetscFree(global_indices);CHKERRQ(ierr);
228545a1bb75SStefano Zampini 
2286674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
2287a717540cSStefano Zampini   ierr = PetscSortInt(total_primal_vertices,aux_primal_numbering);CHKERRQ(ierr);
2288984c4197SStefano Zampini 
2289984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
2290785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2291984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i]=1;
2292984c4197SStefano Zampini   j=total_primal_vertices;
2293984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
22944641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2295674ae819SStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
2296674ae819SStefano Zampini       j++;
2297674ae819SStefano Zampini     }
2298674ae819SStefano Zampini   }
2299674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2300674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2301674ae819SStefano Zampini   /* set values in constraint matrix */
2302984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
2303984c4197SStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,aux_primal_numbering[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2304674ae819SStefano Zampini   }
2305984c4197SStefano Zampini   total_counts = total_primal_vertices;
2306984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
23074641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2308674ae819SStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
2309674ae819SStefano Zampini       ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&total_counts,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],&temp_quadrature_constraint[temp_indices[i]],INSERT_VALUES);CHKERRQ(ierr);
2310674ae819SStefano Zampini       total_counts++;
2311674ae819SStefano Zampini     }
2312674ae819SStefano Zampini   }
2313674ae819SStefano Zampini   /* assembling */
2314674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2315674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2316984c4197SStefano Zampini   /*
231745a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2318984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2319984c4197SStefano Zampini   */
2320674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2321674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2322026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2323984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2324026de310SStefano Zampini     /* iterator on aux_primal_minloc (ordered as read from nearnullspace: vertices, edges and then constraints) */
2325026de310SStefano Zampini     PetscInt     primal_counter;
2326984c4197SStefano Zampini     /* working stuff for GEQRF */
232781d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2328984c4197SStefano Zampini     PetscBLASInt lqr_work;
2329984c4197SStefano Zampini     /* working stuff for UNGQR */
2330984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2331984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2332984c4197SStefano Zampini     /* working stuff for TRTRS */
2333984c4197SStefano Zampini     PetscScalar  *trs_rhs;
23343f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2335984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2336984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2337984c4197SStefano Zampini     PetscScalar  *start_vals;
2338984c4197SStefano Zampini     /* working stuff for values insertion */
23394641a718SStefano Zampini     PetscBT      is_primal;
2340906d46d4SStefano Zampini     /* matrix sizes */
2341906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2342906d46d4SStefano Zampini     /* temporary change of basis */
2343906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2344984c4197SStefano Zampini 
2345906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2346906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
2347906d46d4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
2348*bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
2349906d46d4SStefano Zampini 
2350906d46d4SStefano Zampini     /* nonzeros for local mat */
2351*bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
2352*bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
2353a717540cSStefano Zampini     for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2354a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
2355a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2356a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
2357*bbb9e6c6SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint[temp_indices[i]+j]] = size_of_constraint;
2358a717540cSStefano Zampini         } else {
2359*bbb9e6c6SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint[temp_indices[i]+j]] = 2;
2360a717540cSStefano Zampini           /* get local primal index on the cc */
2361a717540cSStefano Zampini           j = 0;
2362a717540cSStefano Zampini           while (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+j])) j++;
2363*bbb9e6c6SStefano Zampini           nnz[temp_indices_to_constraint[temp_indices[i]+j]] = size_of_constraint;
2364a717540cSStefano Zampini         }
2365a717540cSStefano Zampini       }
2366a717540cSStefano Zampini     }
2367906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2368*bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2369a717540cSStefano Zampini     /* Set initial identity in the matrix */
2370*bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
2371906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2372a717540cSStefano Zampini     }
2373a717540cSStefano Zampini 
2374a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2375a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2376a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2377a717540cSStefano Zampini     }
2378a717540cSStefano Zampini 
2379a717540cSStefano Zampini 
2380a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2381a717540cSStefano Zampini     /*
2382a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2383a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2384a717540cSStefano Zampini 
2385a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2386a717540cSStefano Zampini 
2387a6b551f4SStefano 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)
2388a6b551f4SStefano Zampini 
2389a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2390a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2391a717540cSStefano Zampini             |              ...                        |
2392a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2393a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2394a717540cSStefano Zampini 
2395a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2396a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2397a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2398a6b551f4SStefano Zampini 
2399a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2400a717540cSStefano Zampini     */
2401a717540cSStefano Zampini     if (qr_needed) {
2402984c4197SStefano Zampini       /* space to store Q */
2403854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2404984c4197SStefano Zampini       /* first we issue queries for optimal work */
24053f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
24063f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
24073f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2408984c4197SStefano Zampini       lqr_work = -1;
24093f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2410984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
2411984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
2412785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
2413984c4197SStefano Zampini       lgqr_work = -1;
24143f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
24153f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
24163f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
24173f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
24183f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
24193f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
2420984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
2421984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
2422785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
2423984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
2424785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
2425984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
2426785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
2427a717540cSStefano Zampini       /* allocating workspace for check */
2428a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
2429785e854fSJed Brown         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&work);CHKERRQ(ierr);
2430a717540cSStefano Zampini       }
2431a717540cSStefano Zampini     }
2432984c4197SStefano Zampini     /* array to store whether a node is primal or not */
24334641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
2434473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
24355e8657edSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,aux_primal_numbering,&i,aux_primal_numbering_B);CHKERRQ(ierr);
243639e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
243739e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
24384641a718SStefano Zampini     }
243939e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
244039e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
244139e2fb2aSStefano Zampini     }
244239e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
2443984c4197SStefano Zampini 
2444a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
2445026de310SStefano Zampini     /* -> using implicit ordering contained in temp_indices data */
2446026de310SStefano Zampini     total_counts = pcbddc->n_vertices;
2447026de310SStefano Zampini     primal_counter = total_counts;
2448026de310SStefano Zampini     while (total_counts<pcbddc->local_primal_size) {
2449026de310SStefano Zampini       primal_dofs = 1;
24504641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
2451026de310SStefano Zampini         /* get all constraints with same support: if more then one constraint is present on the cc then surely indices are stored contiguosly */
2452*bbb9e6c6SStefano Zampini         while (total_counts+primal_dofs < pcbddc->local_primal_size && temp_indices_to_constraint[temp_indices[total_counts]] == temp_indices_to_constraint[temp_indices[total_counts+primal_dofs]]) {
2453026de310SStefano Zampini           primal_dofs++;
2454674ae819SStefano Zampini         }
2455984c4197SStefano Zampini         /* get constraint info */
2456026de310SStefano Zampini         size_of_constraint = temp_indices[total_counts+1]-temp_indices[total_counts];
2457984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
2458984c4197SStefano Zampini 
2459984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2460a717540cSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraints %d to %d (incl) need a change of basis (size %d)\n",total_counts,total_counts+primal_dofs-1,size_of_constraint);CHKERRQ(ierr);
2461674ae819SStefano Zampini         }
2462984c4197SStefano Zampini 
2463fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
2464a717540cSStefano Zampini 
2465a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
2466a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
2467a717540cSStefano Zampini             ierr = PetscMemcpy(work,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2468a717540cSStefano Zampini           }
2469984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
2470026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2471984c4197SStefano Zampini 
2472984c4197SStefano Zampini           /* compute QR decomposition of constraints */
24733f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
24743f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
24753f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2476674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
24773f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
2478984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
2479674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2480984c4197SStefano Zampini 
2481984c4197SStefano Zampini           /* explictly compute R^-T */
2482984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
2483984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
24843f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
24853f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
24863f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
24873f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
2488984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
24893f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
2490984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
2491984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2492984c4197SStefano Zampini 
2493a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
24943f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
24953f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
24963f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
24973f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2498984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
24993f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
2500984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
2501984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2502984c4197SStefano Zampini 
2503984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
2504984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
2505984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
25063f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
25073f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
25083f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
25093f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
25103f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
25113f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2512984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2513c4303822SStefano Zampini           PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&zero,&temp_quadrature_constraint[temp_indices[total_counts]],&Blas_LDC));
2514984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2515026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2516984c4197SStefano Zampini 
2517984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
2518*bbb9e6c6SStefano Zampini           start_rows = &temp_indices_to_constraint[temp_indices[total_counts]];
2519984c4197SStefano Zampini           /* insert cols for primal dofs */
2520984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
2521984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
2522*bbb9e6c6SStefano Zampini             start_cols = &temp_indices_to_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter+j]];
2523906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2524984c4197SStefano Zampini           }
2525984c4197SStefano Zampini           /* insert cols for dual dofs */
2526984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
25274641a718SStefano Zampini             if (!PetscBTLookup(is_primal,temp_indices_to_constraint_B[temp_indices[total_counts]+k])) {
2528984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
2529*bbb9e6c6SStefano Zampini               start_cols = &temp_indices_to_constraint[temp_indices[total_counts]+k];
2530906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2531984c4197SStefano Zampini               j++;
2532674ae819SStefano Zampini             }
2533674ae819SStefano Zampini           }
2534984c4197SStefano Zampini 
2535984c4197SStefano Zampini           /* check change of basis */
2536984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
2537984c4197SStefano Zampini             PetscInt   ii,jj;
2538984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
2539c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
2540c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2541c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
2542c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2543c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
2544c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
2545984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2546c4303822SStefano Zampini             PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&Blas_M,&Blas_N,&Blas_K,&one,work,&Blas_LDA,qr_basis,&Blas_LDB,&zero,&work[size_of_constraint*primal_dofs],&Blas_LDC));
2547984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2548984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
2549984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
2550984c4197SStefano Zampini                 if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
2551984c4197SStefano Zampini                 if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
2552674ae819SStefano Zampini               }
2553674ae819SStefano Zampini             }
2554984c4197SStefano Zampini             if (!valid_qr) {
255522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
2556984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
2557984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
2558984c4197SStefano Zampini                   if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
2559984c4197SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not orthogonal to constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
2560674ae819SStefano Zampini                   }
2561984c4197SStefano Zampini                   if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
2562984c4197SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not unitary w.r.t constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
2563984c4197SStefano Zampini                   }
2564984c4197SStefano Zampini                 }
2565984c4197SStefano Zampini               }
2566674ae819SStefano Zampini             } else {
256722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
2568674ae819SStefano Zampini             }
2569674ae819SStefano Zampini           }
2570a717540cSStefano Zampini         } else { /* simple transformation block */
2571a717540cSStefano Zampini           PetscInt    row,col;
2572a6b551f4SStefano Zampini           PetscScalar val,norm;
2573a6b551f4SStefano Zampini 
2574a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2575a6b551f4SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,temp_quadrature_constraint+temp_indices[total_counts],&Blas_one,temp_quadrature_constraint+temp_indices[total_counts],&Blas_one));
2576a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
2577*bbb9e6c6SStefano Zampini             PetscInt row_B = temp_indices_to_constraint_B[temp_indices[total_counts]+j];
2578*bbb9e6c6SStefano Zampini             row = temp_indices_to_constraint[temp_indices[total_counts]+j];
2579*bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
2580*bbb9e6c6SStefano Zampini               col = temp_indices_to_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2581906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
2582a6b551f4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,temp_quadrature_constraint[temp_indices[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
2583a717540cSStefano Zampini             } else {
2584a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
2585*bbb9e6c6SStefano Zampini                 col = temp_indices_to_constraint[temp_indices[total_counts]+k];
2586a717540cSStefano Zampini                 if (row != col) {
2587a717540cSStefano Zampini                   val = -temp_quadrature_constraint[temp_indices[total_counts]+k]/temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2588a717540cSStefano Zampini                 } else {
2589a6b551f4SStefano Zampini                   val = temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]]/norm;
2590a717540cSStefano Zampini                 }
2591906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
2592a717540cSStefano Zampini               }
2593a717540cSStefano Zampini             }
2594a717540cSStefano Zampini           }
259598a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
259622d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
2597a717540cSStefano Zampini           }
2598674ae819SStefano Zampini         }
2599026de310SStefano Zampini         /* increment primal counter */
2600026de310SStefano Zampini         primal_counter += primal_dofs;
2601984c4197SStefano Zampini       } else {
2602984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2603026de310SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %d does not need a change of basis (size %d)\n",total_counts,temp_indices[total_counts+1]-temp_indices[total_counts]);CHKERRQ(ierr);
2604674ae819SStefano Zampini         }
2605674ae819SStefano Zampini       }
2606026de310SStefano Zampini       /* increment constraint counter total_counts */
2607026de310SStefano Zampini       total_counts += primal_dofs;
2608674ae819SStefano Zampini     }
2609a717540cSStefano Zampini 
2610a717540cSStefano Zampini     /* free workspace */
2611a717540cSStefano Zampini     if (qr_needed) {
2612984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
2613984c4197SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
2614984c4197SStefano Zampini       }
2615984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
2616984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
2617984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
2618984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
2619984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
2620674ae819SStefano Zampini     }
2621a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
2622906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2623906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2624906d46d4SStefano Zampini 
2625906d46d4SStefano Zampini     /* assembling of global change of variable */
2626*bbb9e6c6SStefano Zampini     {
2627*bbb9e6c6SStefano Zampini       Mat tmat;
2628906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2629906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2630*bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
2631*bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
2632*bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2633*bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2634906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2635*bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
2636*bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2637*bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2638*bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2639*bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
2640*bbb9e6c6SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2641*bbb9e6c6SStefano Zampini       ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2642*bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
2643*bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
2644906d46d4SStefano Zampini     }
2645906d46d4SStefano Zampini     /* check */
2646906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
2647906d46d4SStefano Zampini       PetscReal error;
2648906d46d4SStefano Zampini       Vec       x,x_change;
2649906d46d4SStefano Zampini 
2650906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
2651906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
2652906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2653906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
2654*bbb9e6c6SStefano Zampini       ierr = VecScatterBegin(matis->ctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2655*bbb9e6c6SStefano Zampini       ierr = VecScatterEnd(matis->ctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2656*bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2657*bbb9e6c6SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2658*bbb9e6c6SStefano Zampini       ierr = VecScatterEnd(matis->ctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2659906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
2660906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2661906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2662906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2663*bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
2664906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
2665906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2666906d46d4SStefano Zampini     }
2667b96c3477SStefano Zampini 
2668b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
2669b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
2670b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
2671b96c3477SStefano Zampini       if (sub_schurs->n_subs_par_g) {
2672b7eb3628SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Change of basis with deluxe scaling and parallel problems still needs to be implemented");
2673b96c3477SStefano Zampini       }
2674b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
2675b96c3477SStefano Zampini         Mat S_1,S_2,tmat;
2676*bbb9e6c6SStefano Zampini         IS is_all_N;
2677*bbb9e6c6SStefano Zampini 
2678*bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
2679*bbb9e6c6SStefano Zampini         ierr = MatGetSubMatrixUnsorted(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
2680*bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
2681b96c3477SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_1);CHKERRQ(ierr);
2682b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
2683b96c3477SStefano Zampini         sub_schurs->S_Ej_all = S_1;
2684b96c3477SStefano Zampini         ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_2);CHKERRQ(ierr);
2685b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
2686b96c3477SStefano Zampini         sub_schurs->sum_S_Ej_all = S_2;
2687b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2688b96c3477SStefano Zampini       }
2689b96c3477SStefano Zampini     }
2690906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
2691906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
2692b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2693b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
2694b9b85e73SStefano Zampini   }
2695906d46d4SStefano Zampini 
2696906d46d4SStefano Zampini   /* set up change of basis context */
2697906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2698906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
2699906d46d4SStefano Zampini 
2700906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
2701906d46d4SStefano Zampini       PetscInt global_size,local_size;
2702906d46d4SStefano Zampini 
2703906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2704906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2705906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
2706906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2707906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
2708906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
2709906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
2710906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
2711906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
2712906d46d4SStefano Zampini     } else {
2713906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
2714906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
2715906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
2716906d46d4SStefano Zampini     }
2717906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
2718906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2719906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
2720906d46d4SStefano Zampini     } else {
2721906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2722906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
2723906d46d4SStefano Zampini     }
2724906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
2725906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
2726906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2727906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2728b9b85e73SStefano Zampini   }
2729a717540cSStefano Zampini 
2730727cdba6SStefano Zampini   /* get indices in local ordering for vertices and constraints */
2731727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) { /* if this is true, I need to check if a new primal space has been introduced */
2732473ba861SJed Brown     ierr = PetscMalloc1(olocal_primal_size,&oprimal_indices_local_idxs);CHKERRQ(ierr);
2733727cdba6SStefano Zampini     ierr = PetscMemcpy(oprimal_indices_local_idxs,pcbddc->primal_indices_local_idxs,olocal_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2734727cdba6SStefano Zampini   }
2735727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2736f347579bSStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2737473ba861SJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2738727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_primal_numbering);CHKERRQ(ierr);
2739727cdba6SStefano Zampini   ierr = PetscMemcpy(pcbddc->primal_indices_local_idxs,aux_primal_numbering,i*sizeof(PetscInt));CHKERRQ(ierr);
2740727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2741727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_primal_numbering);CHKERRQ(ierr);
2742727cdba6SStefano Zampini   ierr = PetscMemcpy(&pcbddc->primal_indices_local_idxs[i],aux_primal_numbering,j*sizeof(PetscInt));CHKERRQ(ierr);
2743727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2744e9189074SStefano Zampini   /* set quantities in PCBDDC data struct */
2745e9189074SStefano Zampini   pcbddc->n_actual_vertices = i;
2746727cdba6SStefano Zampini   /* check if a new primal space has been introduced */
2747727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
2748727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
2749727cdba6SStefano Zampini     ierr = PetscMemcmp(pcbddc->primal_indices_local_idxs,oprimal_indices_local_idxs,olocal_primal_size,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
2750c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
2751727cdba6SStefano Zampini     ierr = PetscFree(oprimal_indices_local_idxs);CHKERRQ(ierr);
2752727cdba6SStefano Zampini   }
2753727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
2754727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2755727cdba6SStefano Zampini 
2756a717540cSStefano Zampini   /* flush dbg viewer */
2757b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
2758b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2759b8ffe317SStefano Zampini   }
2760a717540cSStefano Zampini 
2761e310c8b4SStefano Zampini   /* free workspace */
2762a717540cSStefano Zampini   ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2763a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
2764984c4197SStefano Zampini   ierr = PetscFree(aux_primal_minloc);CHKERRQ(ierr);
27654641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
276608122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
2767906d46d4SStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
2768906d46d4SStefano Zampini     ierr = PetscFree3(temp_quadrature_constraint,temp_indices_to_constraint,temp_indices_to_constraint_B);CHKERRQ(ierr);
276908122e43SStefano Zampini   } else {
277008122e43SStefano Zampini     ierr = PetscFree4(pcbddc->adaptive_constraints_n,
277108122e43SStefano Zampini                       pcbddc->adaptive_constraints_ptrs,
277208122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
277308122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
277408122e43SStefano Zampini     ierr = PetscFree(temp_indices_to_constraint_B);CHKERRQ(ierr);
277508122e43SStefano Zampini   }
2776674ae819SStefano Zampini   PetscFunctionReturn(0);
2777674ae819SStefano Zampini }
2778674ae819SStefano Zampini 
2779674ae819SStefano Zampini #undef __FUNCT__
2780674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
2781674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
2782674ae819SStefano Zampini {
2783674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
2784674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
2785674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
278663602bcaSStefano Zampini   PetscInt    ierr,i,vertex_size;
2787674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
2788674ae819SStefano Zampini 
2789674ae819SStefano Zampini   PetscFunctionBegin;
27908e61c736SStefano Zampini   /* Reset previously computed graph */
27918e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
2792674ae819SStefano Zampini   /* Init local Graph struct */
2793674ae819SStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,matis->mapping);CHKERRQ(ierr);
2794674ae819SStefano Zampini 
2795575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
2796575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
2797575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2798575ad6abSStefano Zampini   }
27999577ea80SStefano Zampini 
2800674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
28014d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
2802674ae819SStefano Zampini     Mat       mat_adj;
28034d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
28044d379d7bSStefano Zampini     PetscInt  nvtxs;
2805674ae819SStefano Zampini     PetscBool flg_row=PETSC_TRUE;
2806674ae819SStefano Zampini 
2807674ae819SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
28084d379d7bSStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2809674ae819SStefano Zampini     if (!flg_row) {
2810674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2811674ae819SStefano Zampini     }
28124d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
28134d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
2814b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
28154d379d7bSStefano Zampini     } else { /* just compute subdomain's connected components */
28164d379d7bSStefano Zampini       IS                     is_dummy;
28174d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
28184d379d7bSStefano Zampini       PetscInt               j,sum;
28194d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
28204d379d7bSStefano Zampini       const PetscInt         *idxs;
28214d379d7bSStefano Zampini       PCBDDCGraph            graph;
28224d379d7bSStefano Zampini       PetscBT                is_on_boundary;
28234d379d7bSStefano Zampini 
28244d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
28254d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
28264d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
28274d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
28284d379d7bSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy);CHKERRQ(ierr);
28294d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
28304d379d7bSStefano Zampini       graph->xadj = xadj;
28314d379d7bSStefano Zampini       graph->adjncy = adjncy;
28324d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
28334d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
28344d379d7bSStefano Zampini 
28354d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
28364d379d7bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains\n",PetscGlobalRank,graph->ncc);CHKERRQ(ierr);
28374d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
28384d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
28394d379d7bSStefano Zampini         }
28404d379d7bSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
28414d379d7bSStefano Zampini       }
28424d379d7bSStefano Zampini 
28434d379d7bSStefano Zampini       ierr = PetscBTCreate(nvtxs,&is_on_boundary);CHKERRQ(ierr);
28444d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
28454d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
28464d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
28474d379d7bSStefano Zampini       }
28484d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
28494d379d7bSStefano Zampini 
28504d379d7bSStefano Zampini       ierr = PetscCalloc1(nvtxs+1,&cxadj);CHKERRQ(ierr);
28514d379d7bSStefano Zampini       sum = 0;
28524d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
28534d379d7bSStefano Zampini         PetscInt sizecc = 0;
28544d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
28554d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
28564d379d7bSStefano Zampini             sizecc++;
28574d379d7bSStefano Zampini           }
28584d379d7bSStefano Zampini         }
28594d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
28604d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
28614d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
28624d379d7bSStefano Zampini           }
28634d379d7bSStefano Zampini         }
28644d379d7bSStefano Zampini         sum += sizecc*sizecc;
28654d379d7bSStefano Zampini       }
28664d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
28674d379d7bSStefano Zampini       sum = 0;
28684d379d7bSStefano Zampini       for (i=0;i<nvtxs;i++) {
28694d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
28704d379d7bSStefano Zampini         cxadj[i] = sum;
28714d379d7bSStefano Zampini         sum += temp;
28724d379d7bSStefano Zampini       }
28734d379d7bSStefano Zampini       cxadj[nvtxs] = sum;
28744d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
28754d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
28764d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
28774d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
28784d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
28794d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
28804d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
28814d379d7bSStefano Zampini                 sizecc++;
28824d379d7bSStefano Zampini               }
28834d379d7bSStefano Zampini             }
28844d379d7bSStefano Zampini           }
28854d379d7bSStefano Zampini         }
28864d379d7bSStefano Zampini       }
28874d379d7bSStefano Zampini       if (nvtxs) {
28884d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
28894d379d7bSStefano Zampini       } else {
28904d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
28914d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
28924d379d7bSStefano Zampini       }
28934d379d7bSStefano Zampini       graph->xadj = 0;
28944d379d7bSStefano Zampini       graph->adjncy = 0;
28954d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
28964d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
28974d379d7bSStefano Zampini     }
28984d379d7bSStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2899674ae819SStefano Zampini     if (!flg_row) {
2900674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2901674ae819SStefano Zampini     }
2902674ae819SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2903674ae819SStefano Zampini   }
2904674ae819SStefano Zampini 
290563602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
2906674ae819SStefano Zampini   vertex_size = 1;
290763602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
290863602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
290995ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
291063602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
2911a7dc3881SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
291263602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2913674ae819SStefano Zampini       }
291463602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
291563602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
291663602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
2917674ae819SStefano Zampini     }
291863602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
2919674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
292063602bcaSStefano Zampini   } else {
292163602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
292263602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
2923854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
292463602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
292563602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
292663602bcaSStefano Zampini       }
292763602bcaSStefano Zampini     }
2928674ae819SStefano Zampini   }
2929674ae819SStefano Zampini 
2930674ae819SStefano Zampini   /* Setup of Graph */
2931785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
2932a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
2933785d1243SStefano Zampini   }
2934785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
2935a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2936785d1243SStefano Zampini   }
293763602bcaSStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);
2938674ae819SStefano Zampini 
2939674ae819SStefano Zampini   /* Graph's connected components analysis */
2940674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
2941674ae819SStefano Zampini 
2942674ae819SStefano Zampini   /* print some info to stdout */
2943674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
2944e49050b4SStefano Zampini     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);
2945674ae819SStefano Zampini   }
2946fb180af4SStefano Zampini 
2947fb180af4SStefano Zampini   /* mark topography has done */
2948fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
2949674ae819SStefano Zampini   PetscFunctionReturn(0);
2950674ae819SStefano Zampini }
2951674ae819SStefano Zampini 
2952674ae819SStefano Zampini #undef __FUNCT__
2953674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalVerticesLocalIdx"
2954f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalVerticesLocalIdx(PC pc, PetscInt *n_vertices, PetscInt **vertices_idx)
2955674ae819SStefano Zampini {
2956674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2957674ae819SStefano Zampini   PetscInt       *vertices,*row_cmat_indices,n,i,size_of_constraint,local_primal_size;
2958674ae819SStefano Zampini   PetscErrorCode ierr;
2959674ae819SStefano Zampini 
2960674ae819SStefano Zampini   PetscFunctionBegin;
2961674ae819SStefano Zampini   n = 0;
2962674ae819SStefano Zampini   vertices = 0;
2963674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
2964674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&i);CHKERRQ(ierr);
2965b120a5c6SStefano Zampini     for (i=0;i<local_primal_size;i++) {
2966b120a5c6SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2967b120a5c6SStefano Zampini       if (size_of_constraint == 1) n++;
2968b120a5c6SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2969b120a5c6SStefano Zampini     }
2970811e8ca2SStefano Zampini     if (vertices_idx) {
2971785e854fSJed Brown       ierr = PetscMalloc1(n,&vertices);CHKERRQ(ierr);
2972b120a5c6SStefano Zampini       n = 0;
2973674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
2974674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2975674ae819SStefano Zampini         if (size_of_constraint == 1) {
2976674ae819SStefano Zampini           vertices[n++]=row_cmat_indices[0];
2977674ae819SStefano Zampini         }
2978674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2979674ae819SStefano Zampini       }
2980674ae819SStefano Zampini     }
2981811e8ca2SStefano Zampini   }
2982674ae819SStefano Zampini   *n_vertices = n;
2983811e8ca2SStefano Zampini   if (vertices_idx) *vertices_idx = vertices;
2984674ae819SStefano Zampini   PetscFunctionReturn(0);
2985674ae819SStefano Zampini }
2986674ae819SStefano Zampini 
2987674ae819SStefano Zampini #undef __FUNCT__
2988674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalConstraintsLocalIdx"
2989f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalConstraintsLocalIdx(PC pc, PetscInt *n_constraints, PetscInt **constraints_idx)
2990674ae819SStefano Zampini {
2991674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2992674ae819SStefano Zampini   PetscInt       *constraints_index,*row_cmat_indices,*row_cmat_global_indices;
2993674ae819SStefano Zampini   PetscInt       n,i,j,size_of_constraint,local_primal_size,local_size,max_size_of_constraint,min_index,min_loc;
29944641a718SStefano Zampini   PetscBT        touched;
2995674ae819SStefano Zampini   PetscErrorCode ierr;
2996674ae819SStefano Zampini 
2997f34684f1SStefano Zampini     /* This function assumes that the number of local constraints per connected component
2998f34684f1SStefano Zampini        is not greater than the number of nodes defined for the connected component
2999f34684f1SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
3000674ae819SStefano Zampini   PetscFunctionBegin;
3001674ae819SStefano Zampini   n = 0;
3002674ae819SStefano Zampini   constraints_index = 0;
3003674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
3004674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&local_size);CHKERRQ(ierr);
3005674ae819SStefano Zampini     max_size_of_constraint = 0;
3006674ae819SStefano Zampini     for (i=0;i<local_primal_size;i++) {
3007674ae819SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
3008674ae819SStefano Zampini       if (size_of_constraint > 1) {
3009674ae819SStefano Zampini         n++;
3010674ae819SStefano Zampini       }
3011674ae819SStefano Zampini       max_size_of_constraint = PetscMax(size_of_constraint,max_size_of_constraint);
3012674ae819SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
3013674ae819SStefano Zampini     }
3014811e8ca2SStefano Zampini     if (constraints_idx) {
3015785e854fSJed Brown       ierr = PetscMalloc1(n,&constraints_index);CHKERRQ(ierr);
3016785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint,&row_cmat_global_indices);CHKERRQ(ierr);
30174641a718SStefano Zampini       ierr = PetscBTCreate(local_size,&touched);CHKERRQ(ierr);
3018674ae819SStefano Zampini       n = 0;
3019674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
3020674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
3021674ae819SStefano Zampini         if (size_of_constraint > 1) {
3022674ae819SStefano Zampini           ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
302382d3d8afSStefano Zampini           /* find first untouched local node */
302482d3d8afSStefano Zampini           j = 0;
30254641a718SStefano Zampini           while (PetscBTLookup(touched,row_cmat_indices[j])) j++;
302682d3d8afSStefano Zampini           min_index = row_cmat_global_indices[j];
302782d3d8afSStefano Zampini           min_loc = j;
302882d3d8afSStefano Zampini           /* search the minimum among nodes not yet touched on the connected component
302982d3d8afSStefano Zampini              since there can be more than one constraint on a single cc */
3030674ae819SStefano Zampini           for (j=1;j<size_of_constraint;j++) {
30314641a718SStefano Zampini             if (!PetscBTLookup(touched,row_cmat_indices[j]) && min_index > row_cmat_global_indices[j]) {
3032674ae819SStefano Zampini               min_index = row_cmat_global_indices[j];
3033674ae819SStefano Zampini               min_loc = j;
3034674ae819SStefano Zampini             }
3035674ae819SStefano Zampini           }
30364641a718SStefano Zampini           ierr = PetscBTSet(touched,row_cmat_indices[min_loc]);CHKERRQ(ierr);
3037674ae819SStefano Zampini           constraints_index[n++] = row_cmat_indices[min_loc];
3038674ae819SStefano Zampini         }
3039674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
3040674ae819SStefano Zampini       }
30414641a718SStefano Zampini       ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
3042674ae819SStefano Zampini       ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
3043811e8ca2SStefano Zampini     }
3044811e8ca2SStefano Zampini   }
3045674ae819SStefano Zampini   *n_constraints = n;
3046811e8ca2SStefano Zampini   if (constraints_idx) *constraints_idx = constraints_index;
3047674ae819SStefano Zampini   PetscFunctionReturn(0);
3048674ae819SStefano Zampini }
3049674ae819SStefano Zampini 
3050674ae819SStefano Zampini #undef __FUNCT__
3051674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3052674ae819SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(MPI_Comm comm,ISLocalToGlobalMapping l2gmap, PetscInt n_local_dofs, PetscInt local_dofs[], PetscInt local_dofs_mult[], PetscInt* n_global_subset, PetscInt* global_numbering_subset[])
3053674ae819SStefano Zampini {
3054674ae819SStefano Zampini   Vec            local_vec,global_vec;
3055674ae819SStefano Zampini   IS             seqis,paris;
3056674ae819SStefano Zampini   VecScatter     scatter_ctx;
3057674ae819SStefano Zampini   PetscScalar    *array;
3058674ae819SStefano Zampini   PetscInt       *temp_global_dofs;
3059674ae819SStefano Zampini   PetscScalar    globalsum;
3060674ae819SStefano Zampini   PetscInt       i,j,s;
3061674ae819SStefano Zampini   PetscInt       nlocals,first_index,old_index,max_local;
3062674ae819SStefano Zampini   PetscMPIInt    rank_prec_comm,size_prec_comm,max_global;
3063674ae819SStefano Zampini   PetscMPIInt    *dof_sizes,*dof_displs;
3064674ae819SStefano Zampini   PetscBool      first_found;
3065674ae819SStefano Zampini   PetscErrorCode ierr;
3066674ae819SStefano Zampini 
3067674ae819SStefano Zampini   PetscFunctionBegin;
3068674ae819SStefano Zampini   /* mpi buffers */
3069b9b85e73SStefano Zampini   ierr = MPI_Comm_size(comm,&size_prec_comm);CHKERRQ(ierr);
3070b9b85e73SStefano Zampini   ierr = MPI_Comm_rank(comm,&rank_prec_comm);CHKERRQ(ierr);
3071674ae819SStefano Zampini   j = ( !rank_prec_comm ? size_prec_comm : 0);
3072785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_sizes);CHKERRQ(ierr);
3073785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_displs);CHKERRQ(ierr);
3074674ae819SStefano Zampini   /* get maximum size of subset */
3075785e854fSJed Brown   ierr = PetscMalloc1(n_local_dofs,&temp_global_dofs);CHKERRQ(ierr);
3076674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingApply(l2gmap,n_local_dofs,local_dofs,temp_global_dofs);CHKERRQ(ierr);
3077674ae819SStefano Zampini   max_local = 0;
3078b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
3079674ae819SStefano Zampini     if (max_local < temp_global_dofs[i] ) {
3080674ae819SStefano Zampini       max_local = temp_global_dofs[i];
3081674ae819SStefano Zampini     }
3082674ae819SStefano Zampini   }
3083b9b85e73SStefano Zampini   ierr = MPI_Allreduce(&max_local,&max_global,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
3084674ae819SStefano Zampini   max_global++;
3085674ae819SStefano Zampini   max_local = 0;
3086b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
3087674ae819SStefano Zampini     if (max_local < local_dofs[i] ) {
3088674ae819SStefano Zampini       max_local = local_dofs[i];
3089674ae819SStefano Zampini     }
3090674ae819SStefano Zampini   }
3091674ae819SStefano Zampini   max_local++;
3092674ae819SStefano Zampini   /* allocate workspace */
3093674ae819SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&local_vec);CHKERRQ(ierr);
3094674ae819SStefano Zampini   ierr = VecSetSizes(local_vec,PETSC_DECIDE,max_local);CHKERRQ(ierr);
3095674ae819SStefano Zampini   ierr = VecSetType(local_vec,VECSEQ);CHKERRQ(ierr);
3096674ae819SStefano Zampini   ierr = VecCreate(comm,&global_vec);CHKERRQ(ierr);
3097674ae819SStefano Zampini   ierr = VecSetSizes(global_vec,PETSC_DECIDE,max_global);CHKERRQ(ierr);
3098674ae819SStefano Zampini   ierr = VecSetType(global_vec,VECMPI);CHKERRQ(ierr);
3099674ae819SStefano Zampini   /* create scatter */
3100674ae819SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_local_dofs,local_dofs,PETSC_COPY_VALUES,&seqis);CHKERRQ(ierr);
3101674ae819SStefano Zampini   ierr = ISCreateGeneral(comm,n_local_dofs,temp_global_dofs,PETSC_COPY_VALUES,&paris);CHKERRQ(ierr);
3102674ae819SStefano Zampini   ierr = VecScatterCreate(local_vec,seqis,global_vec,paris,&scatter_ctx);CHKERRQ(ierr);
3103674ae819SStefano Zampini   ierr = ISDestroy(&seqis);CHKERRQ(ierr);
3104674ae819SStefano Zampini   ierr = ISDestroy(&paris);CHKERRQ(ierr);
3105674ae819SStefano Zampini   /* init array */
3106674ae819SStefano Zampini   ierr = VecSet(global_vec,0.0);CHKERRQ(ierr);
3107674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
3108674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
3109674ae819SStefano Zampini   if (local_dofs_mult) {
3110674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
3111674ae819SStefano Zampini       array[local_dofs[i]]=(PetscScalar)local_dofs_mult[i];
3112674ae819SStefano Zampini     }
3113674ae819SStefano Zampini   } else {
3114674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
3115674ae819SStefano Zampini       array[local_dofs[i]]=1.0;
3116674ae819SStefano Zampini     }
3117674ae819SStefano Zampini   }
3118674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
3119674ae819SStefano Zampini   /* scatter into global vec and get total number of global dofs */
3120674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3121674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3122674ae819SStefano Zampini   ierr = VecSum(global_vec,&globalsum);CHKERRQ(ierr);
31235b08dc53SStefano Zampini   *n_global_subset = (PetscInt)PetscRealPart(globalsum);
3124674ae819SStefano Zampini   /* Fill global_vec with cumulative function for global numbering */
3125674ae819SStefano Zampini   ierr = VecGetArray(global_vec,&array);CHKERRQ(ierr);
3126674ae819SStefano Zampini   ierr = VecGetLocalSize(global_vec,&s);CHKERRQ(ierr);
3127674ae819SStefano Zampini   nlocals = 0;
3128674ae819SStefano Zampini   first_index = -1;
3129674ae819SStefano Zampini   first_found = PETSC_FALSE;
3130674ae819SStefano Zampini   for (i=0;i<s;i++) {
3131b9b85e73SStefano Zampini     if (!first_found && PetscRealPart(array[i]) > 0.1) {
3132674ae819SStefano Zampini       first_found = PETSC_TRUE;
3133674ae819SStefano Zampini       first_index = i;
3134674ae819SStefano Zampini     }
31355b08dc53SStefano Zampini     nlocals += (PetscInt)PetscRealPart(array[i]);
3136674ae819SStefano Zampini   }
3137674ae819SStefano Zampini   ierr = MPI_Gather(&nlocals,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
3138674ae819SStefano Zampini   if (!rank_prec_comm) {
3139674ae819SStefano Zampini     dof_displs[0]=0;
3140674ae819SStefano Zampini     for (i=1;i<size_prec_comm;i++) {
3141674ae819SStefano Zampini       dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
3142674ae819SStefano Zampini     }
3143674ae819SStefano Zampini   }
3144674ae819SStefano Zampini   ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&nlocals,1,MPIU_INT,0,comm);CHKERRQ(ierr);
3145674ae819SStefano Zampini   if (first_found) {
3146674ae819SStefano Zampini     array[first_index] += (PetscScalar)nlocals;
3147674ae819SStefano Zampini     old_index = first_index;
3148674ae819SStefano Zampini     for (i=first_index+1;i<s;i++) {
3149b9b85e73SStefano Zampini       if (PetscRealPart(array[i]) > 0.1) {
3150674ae819SStefano Zampini         array[i] += array[old_index];
3151674ae819SStefano Zampini         old_index = i;
3152674ae819SStefano Zampini       }
3153674ae819SStefano Zampini     }
3154674ae819SStefano Zampini   }
3155674ae819SStefano Zampini   ierr = VecRestoreArray(global_vec,&array);CHKERRQ(ierr);
3156674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
3157674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3158674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3159674ae819SStefano Zampini   /* get global ordering of local dofs */
3160674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
3161674ae819SStefano Zampini   if (local_dofs_mult) {
3162674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
31635b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-local_dofs_mult[i];
3164674ae819SStefano Zampini     }
3165674ae819SStefano Zampini   } else {
3166674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
31675b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-1;
3168674ae819SStefano Zampini     }
3169674ae819SStefano Zampini   }
3170674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
3171674ae819SStefano Zampini   /* free workspace */
3172674ae819SStefano Zampini   ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
3173674ae819SStefano Zampini   ierr = VecDestroy(&local_vec);CHKERRQ(ierr);
3174674ae819SStefano Zampini   ierr = VecDestroy(&global_vec);CHKERRQ(ierr);
3175674ae819SStefano Zampini   ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
3176674ae819SStefano Zampini   ierr = PetscFree(dof_displs);CHKERRQ(ierr);
3177674ae819SStefano Zampini   /* return pointer to global ordering of local dofs */
3178674ae819SStefano Zampini   *global_numbering_subset = temp_global_dofs;
3179674ae819SStefano Zampini   PetscFunctionReturn(0);
3180674ae819SStefano Zampini }
31819a7d3425SStefano Zampini 
31829a7d3425SStefano Zampini #undef __FUNCT__
31839a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
31849a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
31859a7d3425SStefano Zampini {
31869a7d3425SStefano Zampini   PetscInt       i,j;
31879a7d3425SStefano Zampini   PetscScalar    *alphas;
31889a7d3425SStefano Zampini   PetscErrorCode ierr;
31899a7d3425SStefano Zampini 
31909a7d3425SStefano Zampini   PetscFunctionBegin;
31919a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
3192785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
31939a7d3425SStefano Zampini   for (i=0;i<n;i++) {
31949a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
31959a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
31969a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
31979a7d3425SStefano Zampini   }
31989a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
31999a7d3425SStefano Zampini   PetscFunctionReturn(0);
32009a7d3425SStefano Zampini }
32019a7d3425SStefano Zampini 
3202e7931f94SStefano Zampini #undef __FUNCT__
320370cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
320428143c3dSStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscBool contiguous, IS* is_sends)
3205e7931f94SStefano Zampini {
3206e7931f94SStefano Zampini   Mat             subdomain_adj;
3207e7931f94SStefano Zampini   IS              new_ranks,ranks_send_to;
3208e7931f94SStefano Zampini   MatPartitioning partitioner;
3209e7931f94SStefano Zampini   Mat_IS          *matis;
3210e7931f94SStefano Zampini   PetscInt        n_neighs,*neighs,*n_shared,**shared;
3211e7931f94SStefano Zampini   PetscInt        prank;
3212e7931f94SStefano Zampini   PetscMPIInt     size,rank,color;
3213e7931f94SStefano Zampini   PetscInt        *xadj,*adjncy,*oldranks;
3214e7931f94SStefano Zampini   PetscInt        *adjncy_wgt,*v_wgt,*is_indices,*ranks_send_to_idx;
32153837a79fSStefano Zampini   PetscInt        i,local_size,threshold=0;
3216e7931f94SStefano Zampini   PetscErrorCode  ierr;
32172b510759SStefano Zampini   PetscBool       use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
3218e7931f94SStefano Zampini   PetscSubcomm    subcomm;
3219a57a6d2fSStefano Zampini 
3220e7931f94SStefano Zampini   PetscFunctionBegin;
32212b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
32222b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
32232b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
3224e7931f94SStefano Zampini 
3225e7931f94SStefano Zampini   /* Get info on mapping */
3226e7931f94SStefano Zampini   matis = (Mat_IS*)(mat->data);
3227e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&local_size);CHKERRQ(ierr);
3228e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3229e7931f94SStefano Zampini 
3230e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
3231785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
3232e7931f94SStefano Zampini   xadj[0] = 0;
3233e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
3234785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
3235785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
3236e7931f94SStefano Zampini 
32372b510759SStefano Zampini   if (threshold) {
3238d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
32392b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3240d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3241d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3242d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3243d023bfaeSStefano Zampini         xadj_count++;
3244e7931f94SStefano Zampini       }
3245e7931f94SStefano Zampini     }
3246d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3247c8587f34SStefano Zampini   } else {
3248e7931f94SStefano Zampini     if (xadj[1]) {
3249e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3250e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3251c8587f34SStefano Zampini     }
3252e7931f94SStefano Zampini   }
3253e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3254e7931f94SStefano Zampini   if (use_square) {
3255e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3256e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3257e7931f94SStefano Zampini     }
3258e7931f94SStefano Zampini   }
3259e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3260e7931f94SStefano Zampini 
32613837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3262e7931f94SStefano Zampini 
3263e7931f94SStefano Zampini   /*
3264e7931f94SStefano Zampini     Restrict work on active processes only.
3265e7931f94SStefano Zampini   */
3266e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3267e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3268e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
32692b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3270d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3271e7931f94SStefano Zampini   if (color) {
3272e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3273e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3274e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3275c8587f34SStefano Zampini   } else {
327628143c3dSStefano Zampini     PetscInt coarsening_ratio;
3277e7931f94SStefano Zampini     ierr = MPI_Comm_size(subcomm->comm,&size);CHKERRQ(ierr);
3278785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3279e7931f94SStefano Zampini     prank = rank;
3280e7931f94SStefano Zampini     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm->comm);CHKERRQ(ierr);
32818002ef2cSStefano Zampini     /*
3282e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3283e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3284c8587f34SStefano Zampini     }
32858002ef2cSStefano Zampini     */
3286e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3287e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3288c8587f34SStefano Zampini     }
3289e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3290e7931f94SStefano Zampini     ierr = MatCreateMPIAdj(subcomm->comm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
329122b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3292e7931f94SStefano Zampini 
3293e7931f94SStefano Zampini     /* Partition */
3294e7931f94SStefano Zampini     ierr = MatPartitioningCreate(subcomm->comm,&partitioner);CHKERRQ(ierr);
3295e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3296e7931f94SStefano Zampini     if (use_vwgt) {
32973837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3298e7931f94SStefano Zampini       v_wgt[0] = local_size;
3299e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3300c8587f34SStefano Zampini     }
330128143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
330228143c3dSStefano Zampini     coarsening_ratio = size/n_subdomains;
330328143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3304e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3305e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
330622b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3307e7931f94SStefano Zampini 
3308e7931f94SStefano Zampini     ierr = ISGetIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
330928143c3dSStefano Zampini     if (contiguous) {
331028143c3dSStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]]; /* contiguos set of processes */
331128143c3dSStefano Zampini     } else {
331284ba6060SStefano Zampini       ranks_send_to_idx[0] = coarsening_ratio*oldranks[is_indices[0]]; /* scattered set of processes */
331328143c3dSStefano Zampini     }
3314e7931f94SStefano Zampini     ierr = ISRestoreIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3315e7931f94SStefano Zampini     /* clean up */
3316e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
3317e7931f94SStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
3318e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3319e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3320e7931f94SStefano Zampini   }
3321e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3322e7931f94SStefano Zampini 
3323e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3324e7931f94SStefano Zampini   i = 1;
3325e7931f94SStefano Zampini   if (color) i=0;
3326e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3327e7931f94SStefano Zampini 
3328e7931f94SStefano Zampini   /* get back IS */
3329e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3330e7931f94SStefano Zampini   PetscFunctionReturn(0);
3331e7931f94SStefano Zampini }
3332e7931f94SStefano Zampini 
3333e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3334e7931f94SStefano Zampini 
3335e7931f94SStefano Zampini #undef __FUNCT__
3336e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
333728143c3dSStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
3338e7931f94SStefano Zampini {
333970cf5478SStefano Zampini   Mat                    local_mat;
3340e7931f94SStefano Zampini   Mat_IS                 *matis;
3341e7931f94SStefano Zampini   IS                     is_sends_internal;
33429d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
334328143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
33449d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3345e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3346e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3347e7931f94SStefano Zampini   const PetscInt*        is_indices;
3348e7931f94SStefano Zampini   MatType                new_local_type;
3349e7931f94SStefano Zampini   /* buffers */
3350e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
335128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
33529d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3353e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3354e7931f94SStefano Zampini   /* MPI */
335528143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
335628143c3dSStefano Zampini   PetscSubcomm           subcomm;
3357e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
335828143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
335928143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
336028143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
336128143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
336228143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3363e7931f94SStefano Zampini   PetscErrorCode         ierr;
3364e7931f94SStefano Zampini 
3365e7931f94SStefano Zampini   PetscFunctionBegin;
336628143c3dSStefano Zampini   /* TODO: add missing checks */
336728143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
336828143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
336928143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
337028143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3371e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
337228143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3373e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3374e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3375e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3376e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3377e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
337828143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
337970cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
338070cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
338128143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
338270cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
338370cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
338470cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
338570cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
338670cf5478SStefano Zampini   }
3387e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3388e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3389e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3390e7931f94SStefano Zampini   if (!is_sends) {
339128143c3dSStefano Zampini     PetscBool pcontig = PETSC_TRUE;
339228143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
339328143c3dSStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,pcontig,&is_sends_internal);CHKERRQ(ierr);
3394c8587f34SStefano Zampini   } else {
3395e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3396e7931f94SStefano Zampini     is_sends_internal = is_sends;
3397c8587f34SStefano Zampini   }
3398e7931f94SStefano Zampini 
3399e7931f94SStefano Zampini   /* get pointer of MATIS data */
3400e7931f94SStefano Zampini   matis = (Mat_IS*)mat->data;
3401e7931f94SStefano Zampini 
3402e7931f94SStefano Zampini   /* get comm */
3403a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3404e7931f94SStefano Zampini 
3405e7931f94SStefano Zampini   /* compute number of sends */
3406e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3407e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3408e7931f94SStefano Zampini 
3409e7931f94SStefano Zampini   /* compute number of receives */
3410e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3411785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3412e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3413e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3414e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3415e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3416e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3417e7931f94SStefano Zampini 
341828143c3dSStefano Zampini   /* restrict comm if requested */
341928143c3dSStefano Zampini   subcomm = 0;
342028143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
342128143c3dSStefano Zampini   if (restrict_comm) {
342228143c3dSStefano Zampini     PetscMPIInt color,rank,subcommsize;
342328143c3dSStefano Zampini     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
342428143c3dSStefano Zampini     color = 0;
342528143c3dSStefano Zampini     if (n_sends && !n_recvs) color = 1; /* sending only processes will not partecipate in new comm */
342628143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
342728143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
342828143c3dSStefano Zampini     /* check if reuse has been requested */
342928143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
343028143c3dSStefano Zampini       if (*mat_n) {
343128143c3dSStefano Zampini         PetscMPIInt subcommsize2;
343228143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
343328143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
343428143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
343528143c3dSStefano Zampini       } else {
343628143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
343728143c3dSStefano Zampini       }
343828143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
343928143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
344028143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
344128143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
344228143c3dSStefano Zampini       comm_n = subcomm->comm;
344328143c3dSStefano Zampini     }
344428143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
344528143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
344628143c3dSStefano Zampini   } else {
344728143c3dSStefano Zampini     comm_n = comm;
344828143c3dSStefano Zampini   }
344928143c3dSStefano Zampini 
3450e7931f94SStefano Zampini   /* prepare send/receive buffers */
3451785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
3452e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
3453785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
3454e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
345528143c3dSStefano Zampini   if (nis) {
3456854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
345728143c3dSStefano Zampini   }
3458e7931f94SStefano Zampini 
345928143c3dSStefano Zampini   /* Get data from local matrices */
3460e7931f94SStefano Zampini   if (!isdense) {
3461a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
3462e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
3463e7931f94SStefano Zampini     /*
3464e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
3465e7931f94SStefano Zampini        send_buffer_idxs should contain:
3466e7931f94SStefano Zampini        - MatType_PRIVATE type
3467e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
3468e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
3469e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
3470e7931f94SStefano Zampini     */
3471e7931f94SStefano Zampini   } else {
3472e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3473e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&i);CHKERRQ(ierr);
3474854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
3475e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
3476e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
3477e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3478e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
3479e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3480e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
3481e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
3482e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
3483e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
3484c8587f34SStefano Zampini     }
3485c8587f34SStefano Zampini   }
3486e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
348728143c3dSStefano Zampini   /* additional is (if any) */
348828143c3dSStefano Zampini   if (nis) {
348928143c3dSStefano Zampini     PetscMPIInt psum;
349028143c3dSStefano Zampini     PetscInt j;
349128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
349228143c3dSStefano Zampini       PetscInt plen;
349328143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
349428143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
349528143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
349628143c3dSStefano Zampini     }
3497854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
349828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
349928143c3dSStefano Zampini       PetscInt plen;
350028143c3dSStefano Zampini       const PetscInt *is_array_idxs;
350128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
350228143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
350328143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
350428143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
350528143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
350628143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
350728143c3dSStefano Zampini     }
350828143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
350928143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
351028143c3dSStefano Zampini     }
351128143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
351228143c3dSStefano Zampini   }
351328143c3dSStefano Zampini 
3514e7931f94SStefano Zampini   buf_size_idxs = 0;
3515e7931f94SStefano Zampini   buf_size_vals = 0;
351628143c3dSStefano Zampini   buf_size_idxs_is = 0;
3517e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3518e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
3519e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
352028143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
3521e7931f94SStefano Zampini   }
3522785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
3523785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
352495ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
3525e7931f94SStefano Zampini 
3526e7931f94SStefano Zampini   /* get new tags for clean communications */
3527e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
3528e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
352928143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
3530e7931f94SStefano Zampini 
3531e7931f94SStefano Zampini   /* allocate for requests */
3532785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
3533785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
353495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
3535785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
3536785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
353795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
3538e7931f94SStefano Zampini 
3539e7931f94SStefano Zampini   /* communications */
3540e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
3541e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
354228143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
3543e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3544e7931f94SStefano Zampini     source_dest = onodes[i];
3545e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
3546e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
3547e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3548e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
354928143c3dSStefano Zampini     if (nis) {
355028143c3dSStefano 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);
355128143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
355228143c3dSStefano Zampini     }
3553e7931f94SStefano Zampini   }
3554e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
3555e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
3556e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
3557e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
355828143c3dSStefano Zampini     if (nis) {
355928143c3dSStefano 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);
356028143c3dSStefano Zampini     }
3561e7931f94SStefano Zampini   }
3562e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3563e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
3564e7931f94SStefano Zampini 
3565e7931f94SStefano Zampini   /* assemble new l2g map */
3566e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3567e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
35689d30be91SStefano Zampini   new_local_rows = 0;
3569e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
35709d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3571e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3572e7931f94SStefano Zampini   }
35739d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
3574e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
35759d30be91SStefano Zampini   new_local_rows = 0;
3576e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
35779d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
35789d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3579e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3580e7931f94SStefano Zampini   }
35819d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
35829d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
3583e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
3584e7931f94SStefano Zampini 
3585e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
3586e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
3587e7931f94SStefano 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) */
3588e7931f94SStefano Zampini   if (n_recvs) {
358928143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
3590e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
3591e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
3592e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
3593e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
3594e7931f94SStefano Zampini         break;
3595e7931f94SStefano Zampini       }
3596e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
3597e7931f94SStefano Zampini     }
3598e7931f94SStefano Zampini     switch (new_local_type_private) {
359928143c3dSStefano Zampini       case MATDENSE_PRIVATE:
360028143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
3601e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
3602e7931f94SStefano Zampini           bs = 1;
360328143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
360428143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
360528143c3dSStefano Zampini           bs = 1;
360628143c3dSStefano Zampini         }
3607e7931f94SStefano Zampini         break;
3608e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
3609e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
3610e7931f94SStefano Zampini         bs = 1;
3611e7931f94SStefano Zampini         break;
3612e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
3613e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
3614e7931f94SStefano Zampini         break;
3615e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
3616e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
3617e7931f94SStefano Zampini         break;
3618e7931f94SStefano Zampini       default:
36199d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
3620e7931f94SStefano Zampini         break;
3621e7931f94SStefano Zampini     }
362228143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
362328143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
362428143c3dSStefano Zampini     bs = 1;
3625e7931f94SStefano Zampini   }
3626e7931f94SStefano Zampini 
362770cf5478SStefano Zampini   /* create MATIS object if needed */
362870cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
3629e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
363028143c3dSStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,mat_n);CHKERRQ(ierr);
363170cf5478SStefano Zampini   } else {
363270cf5478SStefano Zampini     /* it also destroys the local matrices */
363370cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
363470cf5478SStefano Zampini   }
363570cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
3636e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
36379d30be91SStefano Zampini 
36389d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
36399d30be91SStefano Zampini 
36409d30be91SStefano Zampini   /* Global to local map of received indices */
36419d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
36429d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
36439d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
36449d30be91SStefano Zampini 
36459d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
36469d30be91SStefano Zampini   buf_size_idxs = 0;
36479d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
36489d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
36499d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
36509d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
36519d30be91SStefano Zampini   }
36529d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
36539d30be91SStefano Zampini 
36549d30be91SStefano Zampini   /* set preallocation */
36559d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
36569d30be91SStefano Zampini   if (!newisdense) {
36579d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
36589d30be91SStefano Zampini 
36599d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
36609d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
36619d30be91SStefano Zampini     if (n_recvs) {
36629d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
36639d30be91SStefano Zampini     }
36649d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
36659d30be91SStefano Zampini       PetscInt j;
36669d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
36679d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
36689d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
36699d30be91SStefano Zampini         }
36709d30be91SStefano Zampini       } else {
36719d30be91SStefano Zampini         /* TODO */
36729d30be91SStefano Zampini       }
36739d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
36749d30be91SStefano Zampini     }
36759d30be91SStefano Zampini     if (new_local_nnz) {
36769d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
36779d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
36789d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
36799d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
36809d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
36819d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
36829d30be91SStefano Zampini     } else {
36839d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
36849d30be91SStefano Zampini     }
36859d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
36869d30be91SStefano Zampini   } else {
36879d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
36889d30be91SStefano Zampini   }
3689e7931f94SStefano Zampini 
3690e7931f94SStefano Zampini   /* set values */
3691e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
36929d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
3693e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3694e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
3695e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
36969d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
3697e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3698e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3699e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
370028143c3dSStefano Zampini     } else {
370128143c3dSStefano Zampini       /* TODO */
3702e7931f94SStefano Zampini     }
3703e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3704e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
3705e7931f94SStefano Zampini   }
3706e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3707e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
370870cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
370970cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
37109d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
37119d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
3712e7931f94SStefano Zampini 
3713dfd14d43SStefano Zampini #if 0
371428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
3715e7931f94SStefano Zampini     Vec       lvec,rvec;
3716e7931f94SStefano Zampini     PetscReal infty_error;
3717e7931f94SStefano Zampini 
37182a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
3719e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
3720e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
3721e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
372270cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
3723e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3724e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
3725e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
3726e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
3727e7931f94SStefano Zampini   }
372828143c3dSStefano Zampini #endif
3729e7931f94SStefano Zampini 
373028143c3dSStefano Zampini   /* assemble new additional is (if any) */
373128143c3dSStefano Zampini   if (nis) {
373228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
373328143c3dSStefano Zampini 
373428143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3735854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
373628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
373728143c3dSStefano Zampini     psum = 0;
373828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
373928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
374028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
374128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
374228143c3dSStefano Zampini         psum += plen;
374328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
374428143c3dSStefano Zampini       }
374528143c3dSStefano Zampini     }
3746854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
3747854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
374828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
374928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
375028143c3dSStefano Zampini     }
375128143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
375228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
375328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
375428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
375528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
375628143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
375728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
375828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
375928143c3dSStefano Zampini       }
376028143c3dSStefano Zampini     }
376128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
376228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
376328143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
376428143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
376528143c3dSStefano Zampini     }
376628143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
376728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
376828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
376928143c3dSStefano Zampini   }
3770e7931f94SStefano Zampini   /* free workspace */
377128143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
3772e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3773e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
3774e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3775e7931f94SStefano Zampini   if (isdense) {
3776e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3777e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3778e7931f94SStefano Zampini   } else {
3779e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
3780e7931f94SStefano Zampini   }
378128143c3dSStefano Zampini   if (nis) {
378228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
378328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
378428143c3dSStefano Zampini   }
3785e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
3786e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
378728143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
3788e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
3789e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
379028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
3791e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
3792e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
3793e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
3794e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
3795e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
379628143c3dSStefano Zampini   if (nis) {
379728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
379828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
379928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
380028143c3dSStefano Zampini   }
380128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
380228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
380328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
380428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
380528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
380628143c3dSStefano Zampini     }
380728143c3dSStefano Zampini   }
3808e7931f94SStefano Zampini   PetscFunctionReturn(0);
3809e7931f94SStefano Zampini }
3810a57a6d2fSStefano Zampini 
381112edc857SStefano Zampini /* temporary hack into ksp private data structure */
381212edc857SStefano Zampini #include <petsc-private/kspimpl.h>
381312edc857SStefano Zampini 
3814c8587f34SStefano Zampini #undef __FUNCT__
3815c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
3816c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
3817c8587f34SStefano Zampini {
3818c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
3819c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
382020a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
38219881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
382220a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
38236e683305SStefano Zampini   IS                     coarse_is,*isarray;
38246e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
38256e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
3826f9eb5b7dSStefano Zampini   PC                     pc_temp;
3827c8587f34SStefano Zampini   PCType                 coarse_pc_type;
3828c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
3829f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
38304f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
38316e683305SStefano Zampini   Mat                    t_coarse_mat_is;
38326e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
38336e683305SStefano Zampini   PetscMPIInt            all_procs;
383474e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
383568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
383622bc73bbSStefano Zampini   PetscScalar            *array;
38379881197aSStefano Zampini   PetscErrorCode         ierr;
3838fdc09c96SStefano Zampini 
3839c8587f34SStefano Zampini   PetscFunctionBegin;
3840c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
384168457ee5SStefano 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 */
384268457ee5SStefano Zampini     compute_vecs = PETSC_TRUE;
3843fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
3844fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
3845f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
3846f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
3847f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
3848fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
3849fa7f1dd8SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size) { /* ...but with different size, so reset it and set reuse flag to false */
3850727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3851fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
3852fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
3853fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
3854f4ddd8eeSStefano Zampini       }
3855fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
3856fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
3857f4ddd8eeSStefano Zampini     }
385870cf5478SStefano Zampini     /* reset any subassembling information */
385970cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
38606e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
38616e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
3862fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
3863f4ddd8eeSStefano Zampini   }
3864c8587f34SStefano Zampini 
38656e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
38662b510759SStefano Zampini   im_active = !!(pcis->n);
38672b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
38686e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
38696e683305SStefano Zampini   void_procs = all_procs-active_procs;
38706e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
387174e2c79eSStefano Zampini   redist = PETSC_FALSE;
387222bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
38736e683305SStefano Zampini     csin_ml = PETSC_TRUE;
38746e683305SStefano Zampini     ncoarse_ml = void_procs;
38756e683305SStefano Zampini     csin_ds = PETSC_TRUE;
38766e683305SStefano Zampini     ncoarse_ds = void_procs;
38776e683305SStefano Zampini   } else {
38786e683305SStefano Zampini     csin_ml = PETSC_FALSE;
38796e683305SStefano Zampini     ncoarse_ml = all_procs;
38806e683305SStefano Zampini     if (void_procs) {
38816e683305SStefano Zampini       csin_ds = PETSC_TRUE;
38826e683305SStefano Zampini       ncoarse_ds = void_procs;
38836e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
38846e683305SStefano Zampini     } else {
388574e2c79eSStefano Zampini       if (pcbddc->redistribute_coarse && pcbddc->redistribute_coarse < all_procs) {
388674e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
388774e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
388874e2c79eSStefano Zampini         redist = PETSC_TRUE;
388974e2c79eSStefano Zampini       } else {
38906e683305SStefano Zampini         csin_ds = PETSC_FALSE;
38916e683305SStefano Zampini         ncoarse_ds = all_procs;
38926e683305SStefano Zampini       }
38936e683305SStefano Zampini     }
389474e2c79eSStefano Zampini   }
38956e683305SStefano Zampini 
38966e683305SStefano Zampini   /*
38976e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
38986e683305SStefano Zampini     - we have not exceeded the number of levels requested
38996e683305SStefano Zampini     - we can actually subassemble the active processes
39006e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
39016e683305SStefano Zampini   */
39026e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
39036e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
39046e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
39056e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
39066e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
3907f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
39082b510759SStefano Zampini     } else {
3909f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
3910c8587f34SStefano Zampini     }
3911c8587f34SStefano Zampini   }
39126e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
39136e683305SStefano Zampini   if (multilevel_allowed) {
39146e683305SStefano Zampini     ncoarse = ncoarse_ml;
39156e683305SStefano Zampini     csin = csin_ml;
39166e683305SStefano Zampini   } else {
39176e683305SStefano Zampini     ncoarse = ncoarse_ds;
39186e683305SStefano Zampini     csin = csin_ds;
39196e683305SStefano Zampini   }
3920e7931f94SStefano Zampini 
3921abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
3922abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
3923abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
3924abbbba34SStefano Zampini 
3925abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
392622bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
392722bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
392822bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
392922bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
3930b9b85e73SStefano Zampini #if 0
3931b9b85e73SStefano Zampini   {
3932b9b85e73SStefano Zampini     PetscViewer viewer;
3933b9b85e73SStefano Zampini     char filename[256];
3934b9b85e73SStefano Zampini     sprintf(filename,"local_coarse_mat%d.m",PetscGlobalRank);
3935b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3936b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3937b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
3938b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3939b9b85e73SStefano Zampini   }
3940b9b85e73SStefano Zampini #endif
39416e683305SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)pc),1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_islg,&t_coarse_mat_is);CHKERRQ(ierr);
39426e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
39436e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
39446e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3945abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
3946abbbba34SStefano Zampini 
39476e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
39486e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
39496e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
39506e683305SStefano Zampini     const PetscInt         *idxs;
39516e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
39526e683305SStefano Zampini 
39536e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
39540be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
39556e683305SStefano Zampini     /* allocate space for temporary storage */
3956854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
3957854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
39586e683305SStefano Zampini     /* allocate for IS array */
39596e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
39606e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
39616e683305SStefano Zampini     nis = nisdofs + nisneu;
3962854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
39636e683305SStefano Zampini     /* dofs splitting */
39646e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
39656e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
39666e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
39676e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
39686e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
39696e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
39706e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
39716e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
39726e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
39736e683305SStefano Zampini     }
39746e683305SStefano Zampini     /* neumann boundaries */
39756e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
39766e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
39776e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
39786e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
39796e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
39806e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
39816e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
39826e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
39836e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
39846e683305SStefano Zampini     }
39856e683305SStefano Zampini     /* free memory */
39866e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
39876e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
39886e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
39896e683305SStefano Zampini   } else {
39906e683305SStefano Zampini     nis = 0;
39916e683305SStefano Zampini     nisdofs = 0;
39926e683305SStefano Zampini     nisneu = 0;
39936e683305SStefano Zampini     isarray = NULL;
39946e683305SStefano Zampini   }
39956e683305SStefano Zampini   /* destroy no longer needed map */
39966e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
39976e683305SStefano Zampini 
39986e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
39996e683305SStefano Zampini   coarse_mat_is = NULL;
40006e683305SStefano Zampini   if (csin) {
40016e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
400274e2c79eSStefano Zampini       if (redist) {
400374e2c79eSStefano Zampini         PetscMPIInt rank;
400474e2c79eSStefano Zampini         PetscInt spc,n_spc_p1,dest[1];
400574e2c79eSStefano Zampini 
400674e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
400774e2c79eSStefano Zampini         spc = all_procs/pcbddc->redistribute_coarse;
400874e2c79eSStefano Zampini         n_spc_p1 = all_procs%pcbddc->redistribute_coarse;
400974e2c79eSStefano Zampini         if (rank > n_spc_p1*(spc+1)-1) {
401074e2c79eSStefano Zampini           dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
401174e2c79eSStefano Zampini         } else {
401274e2c79eSStefano Zampini           dest[0] = rank/(spc+1);
401374e2c79eSStefano Zampini         }
401474e2c79eSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),1,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
401574e2c79eSStefano Zampini       } else {
40166e683305SStefano Zampini         PetscInt j,tissize,*nisindices;
40176e683305SStefano Zampini         PetscInt *coarse_candidates;
40186e683305SStefano Zampini         const PetscInt* tisindices;
40196e683305SStefano Zampini         /* get coarse candidates' ranks in pc communicator */
4020854ce69bSBarry Smith         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
40216e683305SStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
40226e683305SStefano Zampini         for (i=0,j=0;i<all_procs;i++) {
40236e683305SStefano Zampini           if (!coarse_candidates[i]) {
40246e683305SStefano Zampini             coarse_candidates[j]=i;
40256e683305SStefano Zampini             j++;
40266e683305SStefano Zampini           }
40276e683305SStefano Zampini         }
40286e683305SStefano Zampini         if (j < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",j,ncoarse);
40296e683305SStefano Zampini         /* get a suitable subassembling pattern */
40306e683305SStefano Zampini         if (csin_type_simple) {
40316e683305SStefano Zampini           PetscMPIInt rank;
40326e683305SStefano Zampini           PetscInt    issize,isidx;
40336e683305SStefano Zampini           ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
40346e683305SStefano Zampini           if (im_active) {
40356e683305SStefano Zampini             issize = 1;
40366e683305SStefano Zampini             isidx = (PetscInt)rank;
40376e683305SStefano Zampini           } else {
40386e683305SStefano Zampini             issize = 0;
40396e683305SStefano Zampini             isidx = -1;
40406e683305SStefano Zampini           }
40416e683305SStefano Zampini           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
40426e683305SStefano Zampini         } else {
40436e683305SStefano Zampini           ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,PETSC_TRUE,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
40446e683305SStefano Zampini         }
40456e683305SStefano Zampini         if (pcbddc->dbg_flag) {
40466e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
40476e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
40486e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
40496e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
40506e683305SStefano Zampini           for (i=0;i<j;i++) {
40516e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
40526e683305SStefano Zampini           }
40536e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
40546e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40556e683305SStefano Zampini         }
40566e683305SStefano Zampini         /* shift the pattern on coarse candidates */
40576e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
40586e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
4059854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
40606e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
40616e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
40626e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
40636e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
40646e683305SStefano Zampini       }
406574e2c79eSStefano Zampini     }
40666e683305SStefano Zampini     if (pcbddc->dbg_flag) {
40676e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
40686e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
40696e683305SStefano Zampini       ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
40706e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40716e683305SStefano Zampini     }
40726e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
40736e683305SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
40746e683305SStefano Zampini   } else {
40756e683305SStefano Zampini     if (pcbddc->dbg_flag) {
40766e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
40776e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
40786e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40796e683305SStefano Zampini     }
40806e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
40816e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
40826e683305SStefano Zampini   }
40836e683305SStefano Zampini 
40846e683305SStefano Zampini   /* create local to global scatters for coarse problem */
408568457ee5SStefano Zampini   if (compute_vecs) {
40866e683305SStefano Zampini     PetscInt lrows;
40876e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
40886e683305SStefano Zampini     if (coarse_mat_is) {
40896e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
40906e683305SStefano Zampini     } else {
40916e683305SStefano Zampini       lrows = 0;
40926e683305SStefano Zampini     }
40936e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
40946e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
40956e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
40966e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
40976e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
40986e683305SStefano Zampini   }
40996e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
41006e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
4101c8587f34SStefano Zampini 
4102f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
4103f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
4104f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
4105f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
4106f9eb5b7dSStefano Zampini   } else {
4107f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
4108f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
4109c8587f34SStefano Zampini   }
4110c8587f34SStefano Zampini 
41116e683305SStefano Zampini   /* print some info if requested */
41126e683305SStefano Zampini   if (pcbddc->dbg_flag) {
41136e683305SStefano Zampini     if (!multilevel_allowed) {
41146e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
41156e683305SStefano Zampini       if (multilevel_requested) {
41166e683305SStefano 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);
41176e683305SStefano Zampini       } else if (pcbddc->max_levels) {
41186e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
41196e683305SStefano Zampini       }
41206e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
41216e683305SStefano Zampini     }
41226e683305SStefano Zampini   }
41236e683305SStefano Zampini 
4124f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
41256e683305SStefano Zampini   if (coarse_mat_is) {
41266e683305SStefano Zampini     MatReuse coarse_mat_reuse;
41276a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
41286e683305SStefano Zampini     if (pcbddc->dbg_flag) {
41296e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
41306e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
41316e683305SStefano Zampini     }
4132f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
4133312be037SStefano Zampini       char prefix[256],str_level[16];
4134e604994aSStefano Zampini       size_t len;
41356e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
4136c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
4137f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
41385f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
4139c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
41406e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
4141c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4142c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4143e604994aSStefano Zampini       /* prefix */
4144e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
4145e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4146e604994aSStefano Zampini       if (!pcbddc->current_level) {
4147e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4148e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
4149c8587f34SStefano Zampini       } else {
4150e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4151312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4152312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
415334d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4154312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4155e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
4156e604994aSStefano Zampini       }
4157e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
4158f9eb5b7dSStefano Zampini       /* allow user customization */
4159f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
41607e0def11SStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4161312be037SStefano Zampini     }
4162f9eb5b7dSStefano Zampini 
4163f9eb5b7dSStefano Zampini     /* get some info after set from options */
4164f9eb5b7dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4165f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
4166f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
41674f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
41686e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
4169f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4170f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
4171f9eb5b7dSStefano Zampini     }
41724f3a063dSStefano Zampini     if (isredundant) {
41734f3a063dSStefano Zampini       KSP inner_ksp;
41744f3a063dSStefano Zampini       PC inner_pc;
41754f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
41764f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
41774f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
41784f3a063dSStefano Zampini     }
4179f9eb5b7dSStefano Zampini 
41806e683305SStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
4181f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
4182f9eb5b7dSStefano Zampini     ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
4183f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
41846e683305SStefano Zampini     if (nisdofs) {
41856e683305SStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
41866e683305SStefano Zampini       for (i=0;i<nisdofs;i++) {
41876e683305SStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
41881035eff8SStefano Zampini       }
41891035eff8SStefano Zampini     }
41906e683305SStefano Zampini     if (nisneu) {
41916e683305SStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
41926e683305SStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
41931035eff8SStefano Zampini     }
4194fdc09c96SStefano Zampini 
4195f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
4196fa7f1dd8SStefano Zampini     if (coarse_reuse) {
419781d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
4198fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
41996e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
4200fa7f1dd8SStefano Zampini     } else {
42016e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
4202fa7f1dd8SStefano Zampini     }
4203c8587f34SStefano Zampini     if (isbddc || isnn) {
420422bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
420570cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
420628143c3dSStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,PETSC_TRUE,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
420722b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
42086e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
42096e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
42106e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
42116e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
421222b6e8a2SStefano Zampini           }
421370cf5478SStefano Zampini         }
42146e683305SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
421570cf5478SStefano Zampini       } else {
421622bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
421722bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
421822bc73bbSStefano Zampini       }
421922bc73bbSStefano Zampini     } else {
42202e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
4221c8587f34SStefano Zampini     }
4222c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
4223c8587f34SStefano Zampini 
4224c8587f34SStefano Zampini     /* propagate symmetry info to coarse matrix */
4225b9d89cd5SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
42265a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
4227c8587f34SStefano Zampini 
42286e683305SStefano Zampini     /* set operators */
42295f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
42306e683305SStefano Zampini     if (pcbddc->dbg_flag) {
42316e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
42326e683305SStefano Zampini     }
42336e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
42346e683305SStefano Zampini     coarse_mat = 0;
42356e683305SStefano Zampini   }
42366e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
4237b9b85e73SStefano Zampini #if 0
4238b9b85e73SStefano Zampini   {
4239b9b85e73SStefano Zampini     PetscViewer viewer;
4240b9b85e73SStefano Zampini     char filename[256];
4241b9b85e73SStefano Zampini     sprintf(filename,"coarse_mat.m");
4242b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,filename,&viewer);CHKERRQ(ierr);
4243b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4244b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4245b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4246b9b85e73SStefano Zampini   }
4247b9b85e73SStefano Zampini #endif
4248c8587f34SStefano Zampini 
4249c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4250c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4251c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
425298a51de6SStefano Zampini   }
425398a51de6SStefano Zampini 
425498a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
425598a51de6SStefano Zampini     Vec crhs,csol;
425698a51de6SStefano Zampini     PetscBool ispreonly;
425798a51de6SStefano Zampini     if (CoarseNullSpace) {
4258c8587f34SStefano Zampini       if (isbddc) {
4259c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4260c8587f34SStefano Zampini       } else {
4261c8587f34SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
4262c8587f34SStefano Zampini       }
4263c8587f34SStefano Zampini     }
4264f9eb5b7dSStefano Zampini     /* setup coarse ksp */
4265f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4266f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4267f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
42686e683305SStefano Zampini     /* hack */
4269f347579bSStefano Zampini     if (!csol) {
42702a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4271f9eb5b7dSStefano Zampini     }
4272f347579bSStefano Zampini     if (!crhs) {
42732a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4274f347579bSStefano Zampini     }
4275cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4276cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
42776e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4278c8587f34SStefano Zampini       KSP       check_ksp;
42792b510759SStefano Zampini       KSPType   check_ksp_type;
4280c8587f34SStefano Zampini       PC        check_pc;
42816e683305SStefano Zampini       Vec       check_vec,coarse_vec;
42826a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
42832b510759SStefano Zampini       PetscInt  its;
42846e683305SStefano Zampini       PetscBool compute_eigs;
42856e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
42866e683305SStefano Zampini       PetscInt  neigs;
42878e185a42SStefano Zampini       const char *prefix;
4288c8587f34SStefano Zampini 
42892b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
42906e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
429123ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4292f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
42932b510759SStefano Zampini       if (ispreonly) {
42942b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
42956e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
42962b510759SStefano Zampini       } else {
4297cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
42986e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4299c8587f34SStefano Zampini       }
4300c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
43016e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
43026e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
43036e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4304a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4305a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4306a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4307a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4308c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4309c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4310c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4311c8587f34SStefano Zampini       /* create random vec */
43126e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
43136e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
4314c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
4315c8587f34SStefano Zampini       if (CoarseNullSpace) {
4316c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
4317c8587f34SStefano Zampini       }
43186e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
4319c8587f34SStefano Zampini       /* solve coarse problem */
43206e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
4321c8587f34SStefano Zampini       if (CoarseNullSpace) {
43226e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
4323c8587f34SStefano Zampini       }
4324cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
43256e683305SStefano Zampini       if (compute_eigs) {
4326854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4327854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
43286e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
43296e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
43306e683305SStefano Zampini         lambda_min = eigs_r[0];
43316e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
43326e683305SStefano Zampini           if (lambda_max>lambda_min) {
4333cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4334cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4335cbcc2c2aSStefano Zampini           }
4336c8587f34SStefano Zampini         }
4337c8587f34SStefano Zampini       }
4338cbcc2c2aSStefano Zampini 
4339c8587f34SStefano Zampini       /* check coarse problem residual error */
43406e683305SStefano Zampini       if (pcbddc->dbg_flag) {
43416e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
43426e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
43436e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4344c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
43456e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
43466e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4347c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
43486e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (%d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
43496e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
43506e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
43516e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
43526e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
43536e683305SStefano Zampini         if (compute_eigs) {
43546e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4355deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4356c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
43576e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
43586e683305SStefano 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);
43596e683305SStefano Zampini           for (i=0;i<neigs;i++) {
43606e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4361c8587f34SStefano Zampini           }
43626e683305SStefano Zampini         }
43636e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
43646e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
43656e683305SStefano Zampini       }
4366c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
43676e683305SStefano Zampini       if (compute_eigs) {
43686e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
43696e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4370c8587f34SStefano Zampini       }
43716e683305SStefano Zampini     }
43726e683305SStefano Zampini   }
4373cbcc2c2aSStefano Zampini   /* print additional info */
4374cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
43756e683305SStefano Zampini     /* waits until all processes reaches this point */
43766e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4377cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4378cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4379cbcc2c2aSStefano Zampini   }
4380cbcc2c2aSStefano Zampini 
43812b510759SStefano Zampini   /* free memory */
4382c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4383fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4384c8587f34SStefano Zampini   PetscFunctionReturn(0);
4385c8587f34SStefano Zampini }
4386674ae819SStefano Zampini 
4387f34684f1SStefano Zampini #undef __FUNCT__
4388f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4389f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4390f34684f1SStefano Zampini {
4391f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4392f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
4393f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
4394727cdba6SStefano Zampini   PetscInt       i,coarse_size;
4395727cdba6SStefano Zampini   PetscInt       *local_primal_indices;
4396f34684f1SStefano Zampini   PetscErrorCode ierr;
4397f34684f1SStefano Zampini 
4398f34684f1SStefano Zampini   PetscFunctionBegin;
4399f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
440089c96988SStefano Zampini   if (!pcbddc->primal_indices_local_idxs && pcbddc->local_primal_size) {
440189c96988SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Local primal indices have not been created");
4402727cdba6SStefano Zampini   }
4403727cdba6SStefano Zampini   ierr = PCBDDCSubsetNumbering(PetscObjectComm((PetscObject)(pc->pmat)),matis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,NULL,&coarse_size,&local_primal_indices);CHKERRQ(ierr);
4404f34684f1SStefano Zampini 
4405f34684f1SStefano Zampini   /* check numbering */
4406f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
4407f34684f1SStefano Zampini     PetscScalar coarsesum,*array;
4408b9b85e73SStefano Zampini     PetscBool set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
4409f34684f1SStefano Zampini 
4410f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4411f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4412f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
44130fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
4414f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4415f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4416727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4417f34684f1SStefano Zampini     }
4418f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4419f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4420f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4421f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4422f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4423f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4424f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4425f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4426f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4427f34684f1SStefano Zampini       if (array[i] == 1.0) {
4428b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
4429f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a single process!\n",PetscGlobalRank,i);CHKERRQ(ierr);
4430f34684f1SStefano Zampini       }
4431f34684f1SStefano Zampini     }
4432b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4433f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4434f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4435f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
4436f34684f1SStefano Zampini     }
4437f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4438f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4439f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4440f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4441f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
4442f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
4443b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
4444f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
4445f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4446f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4447f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
4448727cdba6SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i]);
4449f34684f1SStefano Zampini       }
4450f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4451f34684f1SStefano Zampini     }
4452f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4453b9b85e73SStefano Zampini     if (set_error_reduced) {
4454b9b85e73SStefano Zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
4455b9b85e73SStefano Zampini     }
4456f34684f1SStefano Zampini   }
4457f34684f1SStefano Zampini   /* get back data */
4458f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
4459f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
4460674ae819SStefano Zampini   PetscFunctionReturn(0);
4461674ae819SStefano Zampini }
4462674ae819SStefano Zampini 
4463e456f2a8SStefano Zampini #undef __FUNCT__
4464e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
4465a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
4466e456f2a8SStefano Zampini {
4467e456f2a8SStefano Zampini   IS             localis_t;
4468a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
4469e456f2a8SStefano Zampini   PetscScalar    *vals;
4470e456f2a8SStefano Zampini   PetscErrorCode ierr;
4471e456f2a8SStefano Zampini 
4472e456f2a8SStefano Zampini   PetscFunctionBegin;
4473a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
4474e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
4475854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
4476e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
4477e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4478a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
4479a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
44801035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
4481a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
44821035eff8SStefano Zampini   }
4483a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
4484e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4485e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
4486a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
4487a7dc3881SStefano Zampini   /* now compute set in local ordering */
4488a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4489a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4490a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4491a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
4492a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4493ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4494e456f2a8SStefano Zampini       lsize++;
4495e456f2a8SStefano Zampini     }
4496e456f2a8SStefano Zampini   }
4497854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
4498a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4499ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4500e456f2a8SStefano Zampini       idxs[lsize++] = i;
4501e456f2a8SStefano Zampini     }
4502e456f2a8SStefano Zampini   }
4503a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4504a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
4505e456f2a8SStefano Zampini   *localis = localis_t;
4506e456f2a8SStefano Zampini   PetscFunctionReturn(0);
4507e456f2a8SStefano Zampini }
4508906d46d4SStefano Zampini 
4509906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
4510906d46d4SStefano Zampini #undef __FUNCT__
4511906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
4512906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
4513906d46d4SStefano Zampini {
4514906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4515906d46d4SStefano Zampini   PetscErrorCode   ierr;
4516906d46d4SStefano Zampini 
4517906d46d4SStefano Zampini   PetscFunctionBegin;
4518906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4519906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4520906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4521906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4522906d46d4SStefano Zampini   PetscFunctionReturn(0);
4523906d46d4SStefano Zampini }
4524906d46d4SStefano Zampini 
4525906d46d4SStefano Zampini #undef __FUNCT__
4526906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
4527906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
4528906d46d4SStefano Zampini {
4529906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4530906d46d4SStefano Zampini   PetscErrorCode   ierr;
4531906d46d4SStefano Zampini 
4532906d46d4SStefano Zampini   PetscFunctionBegin;
4533906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4534906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4535906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4536906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4537906d46d4SStefano Zampini   PetscFunctionReturn(0);
4538906d46d4SStefano Zampini }
4539b96c3477SStefano Zampini 
4540b96c3477SStefano Zampini #undef __FUNCT__
4541b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
454208122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
4543b96c3477SStefano Zampini {
4544b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4545b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4546b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
4547b96c3477SStefano Zampini   PetscBool           free_used_adj;
4548b96c3477SStefano Zampini   PetscErrorCode      ierr;
4549b96c3477SStefano Zampini 
4550b96c3477SStefano Zampini   PetscFunctionBegin;
4551b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
4552b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
455308122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
4554b96c3477SStefano Zampini     used_xadj = NULL;
4555b96c3477SStefano Zampini     used_adjncy = NULL;
4556b96c3477SStefano Zampini   } else {
455708122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
455808122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
455908122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
456008122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
4561b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
4562b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
4563b96c3477SStefano Zampini     } else {
4564b96c3477SStefano Zampini       Mat            mat_adj;
4565b96c3477SStefano Zampini       PetscBool      flg_row=PETSC_TRUE;
4566b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
4567b96c3477SStefano Zampini       PetscInt       nvtxs;
4568b96c3477SStefano Zampini 
4569b96c3477SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
4570b96c3477SStefano Zampini       ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4571b96c3477SStefano Zampini       if (!flg_row) {
4572b96c3477SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
4573b96c3477SStefano Zampini       }
4574b96c3477SStefano Zampini       ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
4575b96c3477SStefano Zampini       ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
4576b96c3477SStefano Zampini       ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
4577b96c3477SStefano Zampini       ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4578b96c3477SStefano Zampini       if (!flg_row) {
4579b96c3477SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
4580b96c3477SStefano Zampini       }
4581b96c3477SStefano Zampini       ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
4582b96c3477SStefano Zampini       free_used_adj = PETSC_TRUE;
4583b96c3477SStefano Zampini     }
4584b96c3477SStefano Zampini   }
458508122e43SStefano Zampini   ierr = PCBDDCSubSchursSetUp(sub_schurs,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->adaptive_selection,pcbddc->use_deluxe_scaling,pcbddc->use_edges,pcbddc->use_faces);CHKERRQ(ierr);
4586b96c3477SStefano Zampini 
4587b96c3477SStefano Zampini   /* free adjacency */
4588b96c3477SStefano Zampini   if (free_used_adj) {
4589b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
4590b96c3477SStefano Zampini   }
4591b96c3477SStefano Zampini   PetscFunctionReturn(0);
4592b96c3477SStefano Zampini }
4593b96c3477SStefano Zampini 
4594b96c3477SStefano Zampini #undef __FUNCT__
4595b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
459608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
4597b96c3477SStefano Zampini {
4598b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
4599b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4600b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4601b96c3477SStefano Zampini   PCBDDCGraph         graph;
4602b96c3477SStefano Zampini   Mat                 S_j;
4603b96c3477SStefano Zampini   PetscErrorCode      ierr;
4604b96c3477SStefano Zampini 
4605b96c3477SStefano Zampini   PetscFunctionBegin;
4606b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
460708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
4608b96c3477SStefano Zampini     IS verticesIS;
4609b96c3477SStefano Zampini 
4610b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
4611b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
4612b96c3477SStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap);CHKERRQ(ierr);
4613b96c3477SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticesIS);CHKERRQ(ierr);
4614b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4615b96c3477SStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
4616b96c3477SStefano Zampini /*
4617b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
4618b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4619b96c3477SStefano Zampini     }
4620b96c3477SStefano Zampini */
4621b96c3477SStefano Zampini   } else {
4622b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
4623b96c3477SStefano Zampini   }
4624b96c3477SStefano Zampini 
4625b96c3477SStefano Zampini   /* Create Schur complement matrix */
4626b96c3477SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
4627b96c3477SStefano Zampini   ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
4628b96c3477SStefano Zampini 
4629b96c3477SStefano Zampini   /* sub_schurs init */
463008122e43SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcbddc->local_mat,S_j,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_threshold);CHKERRQ(ierr);
4631b96c3477SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
4632b96c3477SStefano Zampini   /* free graph struct */
463308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
4634b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
4635b96c3477SStefano Zampini   }
4636b96c3477SStefano Zampini   PetscFunctionReturn(0);
4637b96c3477SStefano Zampini }
4638