xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 066566057029b00256acb5d674ad5b0859717d23)
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;
378*06656605SStefano 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);
384*06656605SStefano Zampini   ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
385*06656605SStefano 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);
392*06656605SStefano Zampini   if (pcbddc->local_auxmat2) {
393*06656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
394*06656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
395*06656605SStefano Zampini   }
396674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
397*06656605SStefano 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;
482*06656605SStefano Zampini   /* submatrices of local coarse problem */
483*06656605SStefano Zampini   Mat                    S_VV,S_CV,S_VC,S_CC;
48425084f0cSStefano Zampini   /* working matrices */
485*06656605SStefano Zampini   Mat                    C_CR;
48625084f0cSStefano Zampini   /* additional working stuff */
487*06656605SStefano Zampini   PC                     pc_R;
488*06656605SStefano Zampini   Mat                    F;
489*06656605SStefano Zampini   PetscBool              isLU,isCHOL,isILU;
490*06656605SStefano Zampini 
49125084f0cSStefano Zampini   PetscScalar            *coarse_submat_vals; /* TODO: use a PETSc matrix */
492*06656605SStefano Zampini   PetscScalar            *work;
493*06656605SStefano Zampini   PetscInt               *idx_V_B;
494*06656605SStefano Zampini   PetscInt               n,n_vertices,n_constraints;
495*06656605SStefano 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 */
500*06656605SStefano 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 
521*06656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
522*06656605SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
523*06656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
524*06656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
525*06656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
526*06656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
527*06656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
528*06656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
529*06656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
530*06656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
531*06656605SStefano Zampini 
532*06656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
533*06656605SStefano Zampini   /* allocate workspace */
534*06656605SStefano Zampini   n = 0;
535*06656605SStefano Zampini   if (n_constraints) {
536*06656605SStefano Zampini     n += n_R*n_constraints;
537*06656605SStefano Zampini   }
538*06656605SStefano Zampini   if (n_vertices) {
539*06656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
540*06656605SStefano Zampini   }
541*06656605SStefano Zampini   if (!pcbddc->issym) {
542*06656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
543*06656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
544*06656605SStefano Zampini   }
545*06656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
546*06656605SStefano Zampini 
547*06656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
548*06656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
549*06656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
550*06656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
551*06656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
552*06656605SStefano Zampini   if (isLU || isILU || isCHOL) {
553*06656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
554*06656605SStefano Zampini   } else {
555*06656605SStefano Zampini     F = NULL;
556*06656605SStefano Zampini   }
557*06656605SStefano Zampini 
55888ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
55988ebb749SStefano Zampini   if (n_constraints) {
560*06656605SStefano Zampini     Mat M1,M2,M3;
561*06656605SStefano 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) {
567*06656605SStefano Zampini         PetscScalar *marray;
568*06656605SStefano Zampini 
569*06656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->local_auxmat2,&marray);CHKERRQ(ierr);
570*06656605SStefano 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) {
577*06656605SStefano Zampini       PetscScalar *marray;
578*06656605SStefano Zampini 
579*06656605SStefano Zampini       ierr = PetscMalloc1(2*n_R*n_constraints,&marray);CHKERRQ(ierr);
580*06656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,marray,&pcbddc->local_auxmat2);CHKERRQ(ierr);
581*06656605SStefano Zampini       marray += n_R*n_constraints;
582*06656605SStefano 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 */
591*06656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
59288ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
593*06656605SStefano Zampini       const PetscScalar *row_cmat_values;
594*06656605SStefano Zampini       const PetscInt    *row_cmat_indices;
595*06656605SStefano Zampini       PetscInt          size_of_constraint,j;
59688ebb749SStefano Zampini 
597*06656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
598*06656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
599*06656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
600*06656605SStefano Zampini       }
601*06656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
602*06656605SStefano Zampini     }
603*06656605SStefano Zampini     if (F) {
604*06656605SStefano Zampini       Mat B;
605*06656605SStefano Zampini 
606*06656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
607*06656605SStefano Zampini       ierr = MatMatSolve(F,B,pcbddc->local_auxmat2);CHKERRQ(ierr);
608*06656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
609*06656605SStefano Zampini     } else {
610*06656605SStefano Zampini       PetscScalar *xarray;
611*06656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&xarray);CHKERRQ(ierr);
612*06656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
613*06656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
614*06656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,xarray+i*n_R);CHKERRQ(ierr);
615*06656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
616*06656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
617*06656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
618*06656605SStefano Zampini       }
619*06656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&xarray);CHKERRQ(ierr);
620*06656605SStefano Zampini     }
621*06656605SStefano Zampini 
622*06656605SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
623*06656605SStefano 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);
625*06656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
626*06656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
62725084f0cSStefano Zampini     ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
628*06656605SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,m_one);CHKERRQ(ierr);
629*06656605SStefano 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);
633*06656605SStefano 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);
635*06656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
636*06656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
63788ebb749SStefano Zampini   }
63888ebb749SStefano Zampini 
63988ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
64088ebb749SStefano Zampini   if (n_vertices) {
641*06656605SStefano Zampini     Mat       newmat;
642*06656605SStefano 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);
662*06656605SStefano 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) {
674*06656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
675*06656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
676*06656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
677*06656605SStefano Zampini     }
678f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
679*06656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
680*06656605SStefano Zampini       PetscScalar *marray;
681*06656605SStefano Zampini 
682*06656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
683*06656605SStefano 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   }
690*06656605SStefano Zampini 
691f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
692*06656605SStefano Zampini     PetscScalar *marray;
69388ebb749SStefano Zampini 
694*06656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
6958eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
696*06656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
69788ebb749SStefano Zampini     }
698b9d89cd5SStefano Zampini     if (!pcbddc->issym) {
699*06656605SStefano Zampini       n *= 2;
700f4ddd8eeSStefano Zampini     }
701*06656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
702*06656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
703*06656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
704*06656605SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
705*06656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
706*06656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
70788ebb749SStefano Zampini     }
708*06656605SStefano Zampini     if (!pcbddc->issym) {
709*06656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
710*06656605SStefano Zampini       if (pcbddc->switch_static) {
711*06656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
712*06656605SStefano 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;
717*06656605SStefano 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     }
722*06656605SStefano Zampini   }
723*06656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
724*06656605SStefano Zampini   /* vertices */
725*06656605SStefano Zampini   if (n_vertices) {
726*06656605SStefano Zampini     Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
727*06656605SStefano Zampini     PetscScalar  *x,*y;
728*06656605SStefano Zampini     PetscBLASInt B_N,B_one = 1;
729*06656605SStefano Zampini 
730*06656605SStefano Zampini     ierr = PetscMemzero(work,2*n_R*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
731*06656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
732*06656605SStefano Zampini     ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
733*06656605SStefano Zampini     if (F) {
734*06656605SStefano Zampini       ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
735*06656605SStefano Zampini     } else {
736*06656605SStefano Zampini       ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
737*06656605SStefano Zampini       for (i=0;i<n_vertices;i++) {
738*06656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
739*06656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
740*06656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
741*06656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
742*06656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
743*06656605SStefano Zampini       }
744*06656605SStefano Zampini       ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
745*06656605SStefano Zampini     }
746*06656605SStefano Zampini     ierr = MatScale(A_RRmA_RV,m_one);CHKERRQ(ierr);
747*06656605SStefano Zampini     /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
748*06656605SStefano Zampini     if (n_constraints) {
749*06656605SStefano Zampini       Mat B;
750*06656605SStefano Zampini       ierr = MatMatMult(pcbddc->local_auxmat1,A_RRmA_RV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
751*06656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
752*06656605SStefano Zampini       ierr = MatMatMult(pcbddc->local_auxmat2,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
753*06656605SStefano Zampini       ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
754*06656605SStefano Zampini       ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
755*06656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
756*06656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
757*06656605SStefano Zampini     }
758*06656605SStefano Zampini     ierr = MatConvert(A_VR,impMatType,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
759*06656605SStefano Zampini     ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
760*06656605SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
761*06656605SStefano Zampini     ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
762*06656605SStefano Zampini     ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
763*06656605SStefano Zampini     ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
764*06656605SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
765*06656605SStefano Zampini     ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
766*06656605SStefano Zampini     ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
767*06656605SStefano Zampini     ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
768*06656605SStefano Zampini     ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
769*06656605SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
770*06656605SStefano Zampini     /* coarse basis functions */
771*06656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
772*06656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
773*06656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
774*06656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
775*06656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
776*06656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
777*06656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
778*06656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
779*06656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
780*06656605SStefano Zampini 
781*06656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
782*06656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
783*06656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
784*06656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
785*06656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
786*06656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
787*06656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
788*06656605SStefano Zampini       }
789*06656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
790*06656605SStefano Zampini     }
791*06656605SStefano Zampini     ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
792*06656605SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
793*06656605SStefano Zampini   }
794*06656605SStefano Zampini 
795*06656605SStefano Zampini   if (n_constraints) {
796*06656605SStefano Zampini     Mat B;
797*06656605SStefano Zampini 
798*06656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
799*06656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
800*06656605SStefano Zampini     ierr = MatMatMult(pcbddc->local_auxmat2,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
801*06656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
802*06656605SStefano Zampini     if (n_vertices) {
803*06656605SStefano Zampini       ierr = MatMatMult(A_VR,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_VC);CHKERRQ(ierr);
804*06656605SStefano Zampini     }
805*06656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
806*06656605SStefano Zampini     /* coarse basis functions */
807*06656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
808*06656605SStefano Zampini       PetscScalar *y;
809*06656605SStefano Zampini 
810*06656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
811*06656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
812*06656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
813*06656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
814*06656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
815*06656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
816*06656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
817*06656605SStefano Zampini 
818*06656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
819*06656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
820*06656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
821*06656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
822*06656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
823*06656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
824*06656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
825*06656605SStefano Zampini       }
826*06656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
827*06656605SStefano Zampini     }
828*06656605SStefano Zampini   }
829*06656605SStefano Zampini 
830*06656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
831*06656605SStefano Zampini   if (!pcbddc->issym) {
832*06656605SStefano Zampini     Mat B,X;
833*06656605SStefano Zampini 
834*06656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,pcbddc->local_primal_size,work,&B);CHKERRQ(ierr);
835*06656605SStefano Zampini 
836*06656605SStefano Zampini     if (n_constraints) {
837*06656605SStefano Zampini       Mat S_VCT,S_CCT,B_C;
838*06656605SStefano Zampini 
839*06656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
840*06656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
841*06656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
842*06656605SStefano Zampini       if (n_vertices) {
843*06656605SStefano Zampini         Mat B_V;
844*06656605SStefano Zampini 
845*06656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
846*06656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
847*06656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
848*06656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
849*06656605SStefano Zampini       }
850*06656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
851*06656605SStefano Zampini     }
852*06656605SStefano Zampini     if (n_vertices) {
853*06656605SStefano Zampini       Mat          A_VRT;
854*06656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
855*06656605SStefano Zampini 
856*06656605SStefano Zampini       if (!n_constraints) { /* if there are no constraints, reset work */
857*06656605SStefano Zampini         ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
858*06656605SStefano Zampini       }
859*06656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+pcbddc->local_primal_size*n_R,&A_VRT);CHKERRQ(ierr);
860*06656605SStefano Zampini       ierr = MatTranspose(A_VR,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
861*06656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
862*06656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,work+pcbddc->local_primal_size*n_R,&B_one,work,&B_one));
863*06656605SStefano Zampini     }
864*06656605SStefano Zampini 
865*06656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,pcbddc->local_primal_size,work+pcbddc->local_primal_size*n_R,&X);CHKERRQ(ierr);
866*06656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
867*06656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
868*06656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
869*06656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
870*06656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
871*06656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
872*06656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
873*06656605SStefano Zampini       }
874*06656605SStefano Zampini     } else {
875*06656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
876*06656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
877*06656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
878*06656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
879*06656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
880*06656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
881*06656605SStefano Zampini       }
882*06656605SStefano Zampini     }
883*06656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
884*06656605SStefano Zampini     /* coarse basis functions */
885*06656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
886*06656605SStefano Zampini       PetscScalar *y;
887*06656605SStefano Zampini 
888*06656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
889*06656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
890*06656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
891*06656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
892*06656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
893*06656605SStefano Zampini       if (i<n_vertices) {
894*06656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
895*06656605SStefano Zampini       }
896*06656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
897*06656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
898*06656605SStefano Zampini 
899*06656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
900*06656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
901*06656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
902*06656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
903*06656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
904*06656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
905*06656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
906*06656605SStefano Zampini       }
907*06656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
908*06656605SStefano Zampini     }
909*06656605SStefano Zampini     ierr = MatDestroy(&X);CHKERRQ(ierr);
910*06656605SStefano Zampini   }
911*06656605SStefano Zampini 
91288ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
913*06656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
914*06656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
915*06656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
916*06656605SStefano 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);
942*06656605SStefano 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);
973*06656605SStefano Zampini 
9740fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
975*06656605SStefano 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   }
993*06656605SStefano Zampini 
99488ebb749SStefano Zampini   /* free memory */
995*06656605SStefano 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 
215208122e43SStefano Zampini     temp_indices = pcbddc->adaptive_constraints_ptrs;
215308122e43SStefano Zampini     temp_indices_to_constraint = pcbddc->adaptive_constraints_idxs;
215408122e43SStefano Zampini     temp_quadrature_constraint = pcbddc->adaptive_constraints_data;
215508122e43SStefano Zampini 
215608122e43SStefano Zampini #if 0
215708122e43SStefano Zampini     printf("Found %d totals\n",total_counts);
215808122e43SStefano Zampini     for (i=0;i<total_counts;i++) {
215908122e43SStefano Zampini       printf("const %d, start %d",i,temp_indices[i]);
216008122e43SStefano Zampini       printf(" end %d:\n",temp_indices[i+1]);
216108122e43SStefano Zampini       for (j=temp_indices[i];j<temp_indices[i+1];j++) {
216208122e43SStefano Zampini         printf("  idxs %d",temp_indices_to_constraint[j]);
216308122e43SStefano Zampini         printf("  data %1.2e\n",temp_quadrature_constraint[j]);
216408122e43SStefano Zampini       }
216508122e43SStefano Zampini     }
216608122e43SStefano Zampini #endif
216708122e43SStefano Zampini 
216808122e43SStefano Zampini     for (i=0;i<total_counts;i++) max_size_of_constraint = PetscMax(max_size_of_constraint,temp_indices[i+1]-temp_indices[i]);
216908122e43SStefano Zampini     ierr = PetscMalloc1(temp_indices[total_counts],&temp_indices_to_constraint_B);CHKERRQ(ierr);
217008122e43SStefano Zampini     /* Change of basis */
217108122e43SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
217208122e43SStefano Zampini     cum = 0;
217308122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
217408122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
217508122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
217608122e43SStefano Zampini           for (j=0;j<pcbddc->adaptive_constraints_n[i];j++) {
217708122e43SStefano Zampini             ierr = PetscBTSet(change_basis,cum+j);CHKERRQ(ierr);
217808122e43SStefano Zampini           }
217908122e43SStefano Zampini         }
218008122e43SStefano Zampini         cum += pcbddc->adaptive_constraints_n[i];
218108122e43SStefano Zampini       }
218208122e43SStefano Zampini     }
218308122e43SStefano Zampini   }
218408122e43SStefano Zampini 
218508122e43SStefano Zampini   /* free index sets of faces, edges and vertices */
218608122e43SStefano Zampini   for (i=0;i<n_ISForFaces;i++) {
218708122e43SStefano Zampini     ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
218808122e43SStefano Zampini   }
218908122e43SStefano Zampini   if (n_ISForFaces) {
219008122e43SStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
219108122e43SStefano Zampini   }
219208122e43SStefano Zampini   for (i=0;i<n_ISForEdges;i++) {
219308122e43SStefano Zampini     ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
219408122e43SStefano Zampini   }
219508122e43SStefano Zampini   if (n_ISForEdges) {
219608122e43SStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
219708122e43SStefano Zampini   }
219808122e43SStefano Zampini   ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
219908122e43SStefano Zampini 
220008122e43SStefano Zampini   /* map temp_indices_to_constraint in boundary numbering */
220108122e43SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,temp_indices[total_counts],temp_indices_to_constraint,&i,temp_indices_to_constraint_B);CHKERRQ(ierr);
220208122e43SStefano Zampini   if (i != temp_indices[total_counts]) {
220308122e43SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",temp_indices[total_counts],i);
220408122e43SStefano Zampini   }
2205984c4197SStefano Zampini 
2206727cdba6SStefano Zampini   /* set quantities in pcbddc data structure and store previous primal size */
2207984c4197SStefano Zampini   /* n_vertices defines the number of subdomain corners in the primal space */
2208674ae819SStefano Zampini   /* n_constraints defines the number of averages (they can be point primal dofs if change of basis is requested) */
2209727cdba6SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
2210984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
2211674ae819SStefano Zampini   pcbddc->n_vertices = n_vertices;
2212984c4197SStefano Zampini   pcbddc->n_constraints = pcbddc->local_primal_size-pcbddc->n_vertices;
2213674ae819SStefano Zampini 
2214674ae819SStefano Zampini   /* Create constraint matrix */
2215674ae819SStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
2216674ae819SStefano Zampini   /* so we need to set it up properly either with or without change of basis */
2217674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2218674ae819SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
2219984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
2220984c4197SStefano Zampini   /* array to compute a local numbering of constraints : vertices first then constraints */
2221785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_numbering);CHKERRQ(ierr);
2222984c4197SStefano Zampini   /* array to select the proper local node (of minimum index with respect to global ordering) when changing the basis */
2223984c4197SStefano 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 */
2224785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_minloc);CHKERRQ(ierr);
2225984c4197SStefano Zampini   /* auxiliary stuff for basis change */
2226785e854fSJed Brown   ierr = PetscMalloc1(max_size_of_constraint,&global_indices);CHKERRQ(ierr);
22274641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n_B,&touched);CHKERRQ(ierr);
2228984c4197SStefano Zampini 
2229984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
2230984c4197SStefano Zampini   total_primal_vertices=0;
2231984c4197SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
2232674ae819SStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
2233984c4197SStefano Zampini     if (size_of_constraint == 1) {
22344641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]]);CHKERRQ(ierr);
2235984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]];
2236984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=0;
2237984c4197SStefano Zampini       total_primal_vertices++;
22384641a718SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) { /* Same procedure used in PCBDDCGetPrimalConstraintsLocalIdx */
2239984c4197SStefano Zampini       PetscInt min_loc,min_index;
2240984c4197SStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],global_indices);CHKERRQ(ierr);
2241984c4197SStefano Zampini       /* find first untouched local node */
2242674ae819SStefano Zampini       k = 0;
22434641a718SStefano Zampini       while (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) k++;
2244984c4197SStefano Zampini       min_index = global_indices[k];
2245984c4197SStefano Zampini       min_loc = k;
2246984c4197SStefano Zampini       /* search the minimum among global nodes already untouched on the cc */
2247984c4197SStefano Zampini       for (k=1;k<size_of_constraint;k++) {
2248984c4197SStefano Zampini         /* there can be more than one constraint on a single connected component */
22494641a718SStefano Zampini         if (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k]) && min_index > global_indices[k]) {
2250984c4197SStefano Zampini           min_index = global_indices[k];
2251984c4197SStefano Zampini           min_loc = k;
2252674ae819SStefano Zampini         }
2253674ae819SStefano Zampini       }
22544641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]+min_loc]);CHKERRQ(ierr);
2255984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]+min_loc];
2256984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=min_loc;
2257984c4197SStefano Zampini       total_primal_vertices++;
2258984c4197SStefano Zampini     }
2259984c4197SStefano Zampini   }
2260a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
2261a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
2262a717540cSStefano Zampini   ierr = PetscBTCreate(pcbddc->local_primal_size,&qr_needed_idx);CHKERRQ(ierr);
2263a717540cSStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2264a717540cSStefano Zampini     if (PetscBTLookup(change_basis,i)) {
2265fa434743SStefano Zampini       if (!pcbddc->use_qr_single) {
2266a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2267a717540cSStefano Zampini         j = 0;
2268a717540cSStefano Zampini         for (k=0;k<size_of_constraint;k++) {
2269a717540cSStefano Zampini           if (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) {
2270a717540cSStefano Zampini             j++;
2271a717540cSStefano Zampini           }
2272a717540cSStefano Zampini         }
2273a717540cSStefano Zampini         /* found more than one primal dof on the cc */
2274a717540cSStefano Zampini         if (j > 1) {
2275a717540cSStefano Zampini           PetscBTSet(qr_needed_idx,i);
2276a717540cSStefano Zampini           qr_needed = PETSC_TRUE;
2277a717540cSStefano Zampini         }
2278fa434743SStefano Zampini       } else {
2279fa434743SStefano Zampini         PetscBTSet(qr_needed_idx,i);
2280fa434743SStefano Zampini         qr_needed = PETSC_TRUE;
2281fa434743SStefano Zampini       }
2282a717540cSStefano Zampini     }
2283a717540cSStefano Zampini   }
2284984c4197SStefano Zampini   /* free workspace */
2285984c4197SStefano Zampini   ierr = PetscFree(global_indices);CHKERRQ(ierr);
228645a1bb75SStefano Zampini 
2287674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
2288a717540cSStefano Zampini   ierr = PetscSortInt(total_primal_vertices,aux_primal_numbering);CHKERRQ(ierr);
2289984c4197SStefano Zampini 
2290984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
2291785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2292984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i]=1;
2293984c4197SStefano Zampini   j=total_primal_vertices;
2294984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
22954641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2296674ae819SStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
2297674ae819SStefano Zampini       j++;
2298674ae819SStefano Zampini     }
2299674ae819SStefano Zampini   }
2300674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2301674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2302674ae819SStefano Zampini   /* set values in constraint matrix */
2303984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
2304984c4197SStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,aux_primal_numbering[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2305674ae819SStefano Zampini   }
2306984c4197SStefano Zampini   total_counts = total_primal_vertices;
2307984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
23084641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2309674ae819SStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
2310674ae819SStefano 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);
2311674ae819SStefano Zampini       total_counts++;
2312674ae819SStefano Zampini     }
2313674ae819SStefano Zampini   }
2314674ae819SStefano Zampini   /* assembling */
2315674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2316674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2317984c4197SStefano Zampini   /*
231845a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2319984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2320984c4197SStefano Zampini   */
2321674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2322674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2323026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2324984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2325026de310SStefano Zampini     /* iterator on aux_primal_minloc (ordered as read from nearnullspace: vertices, edges and then constraints) */
2326026de310SStefano Zampini     PetscInt     primal_counter;
2327984c4197SStefano Zampini     /* working stuff for GEQRF */
232881d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2329984c4197SStefano Zampini     PetscBLASInt lqr_work;
2330984c4197SStefano Zampini     /* working stuff for UNGQR */
2331984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2332984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2333984c4197SStefano Zampini     /* working stuff for TRTRS */
2334984c4197SStefano Zampini     PetscScalar  *trs_rhs;
23353f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2336984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2337984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2338984c4197SStefano Zampini     PetscScalar  *start_vals;
2339984c4197SStefano Zampini     /* working stuff for values insertion */
23404641a718SStefano Zampini     PetscBT      is_primal;
2341906d46d4SStefano Zampini     /* matrix sizes */
2342906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2343906d46d4SStefano Zampini     /* work array for nonzeros */
2344906d46d4SStefano Zampini     PetscScalar  *nnz_array;
2345906d46d4SStefano Zampini     /* temporary change of basis */
2346906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2347906d46d4SStefano Zampini     /* auxiliary work for global change of basis */
2348906d46d4SStefano Zampini     Vec          nnz_vec;
234922bc73bbSStefano Zampini     PetscInt     *idxs_I,*idxs_B,*idxs_all,*d_nnz,*o_nnz;
2350906d46d4SStefano Zampini     PetscInt     nvtxs,*xadj,*adjncy,*idxs_mapped;
2351906d46d4SStefano Zampini     PetscScalar  *vals;
2352906d46d4SStefano Zampini     PetscBool    done;
2353984c4197SStefano Zampini 
2354906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2355906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
2356906d46d4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
2357906d46d4SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n_B,pcis->n_B,pcis->n_B,pcis->n_B);CHKERRQ(ierr);
2358906d46d4SStefano Zampini 
2359906d46d4SStefano Zampini     /* nonzeros for local mat */
2360785e854fSJed Brown     ierr = PetscMalloc1(pcis->n_B,&nnz);CHKERRQ(ierr);
2361a717540cSStefano Zampini     for (i=0;i<pcis->n_B;i++) nnz[i]=1;
2362a717540cSStefano Zampini     for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2363a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
2364a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2365a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
2366a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2367a717540cSStefano Zampini         } else {
2368a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = 2;
2369a717540cSStefano Zampini           /* get local primal index on the cc */
2370a717540cSStefano Zampini           j = 0;
2371a717540cSStefano Zampini           while (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+j])) j++;
2372a717540cSStefano Zampini           nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2373a717540cSStefano Zampini         }
2374a717540cSStefano Zampini       }
2375a717540cSStefano Zampini     }
2376906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2377a717540cSStefano Zampini     /* Set initial identity in the matrix */
2378a717540cSStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2379906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2380a717540cSStefano Zampini     }
2381a717540cSStefano Zampini 
2382a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2383a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2384a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2385a717540cSStefano Zampini     }
2386a717540cSStefano Zampini 
2387a717540cSStefano Zampini 
2388a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2389a717540cSStefano Zampini     /*
2390a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2391a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2392a717540cSStefano Zampini 
2393a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2394a717540cSStefano Zampini 
2395a6b551f4SStefano 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)
2396a6b551f4SStefano Zampini 
2397a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2398a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2399a717540cSStefano Zampini             |              ...                        |
2400a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2401a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2402a717540cSStefano Zampini 
2403a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2404a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2405a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2406a6b551f4SStefano Zampini 
2407a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2408a717540cSStefano Zampini     */
2409a717540cSStefano Zampini     if (qr_needed) {
2410984c4197SStefano Zampini       /* space to store Q */
2411854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2412984c4197SStefano Zampini       /* first we issue queries for optimal work */
24133f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
24143f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
24153f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2416984c4197SStefano Zampini       lqr_work = -1;
24173f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2418984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
2419984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
2420785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
2421984c4197SStefano Zampini       lgqr_work = -1;
24223f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
24233f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
24243f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
24253f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
24263f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
24273f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
2428984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
2429984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
2430785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
2431984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
2432785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
2433984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
2434785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
2435a717540cSStefano Zampini       /* allocating workspace for check */
2436a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
2437785e854fSJed Brown         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&work);CHKERRQ(ierr);
2438a717540cSStefano Zampini       }
2439a717540cSStefano Zampini     }
2440984c4197SStefano Zampini     /* array to store whether a node is primal or not */
24414641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
2442473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
24435e8657edSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,aux_primal_numbering,&i,aux_primal_numbering_B);CHKERRQ(ierr);
244439e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
244539e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
24464641a718SStefano Zampini     }
244739e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
244839e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
244939e2fb2aSStefano Zampini     }
245039e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
2451984c4197SStefano Zampini 
2452a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
2453026de310SStefano Zampini     /* -> using implicit ordering contained in temp_indices data */
2454026de310SStefano Zampini     total_counts = pcbddc->n_vertices;
2455026de310SStefano Zampini     primal_counter = total_counts;
2456026de310SStefano Zampini     while (total_counts<pcbddc->local_primal_size) {
2457026de310SStefano Zampini       primal_dofs = 1;
24584641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
2459026de310SStefano Zampini         /* get all constraints with same support: if more then one constraint is present on the cc then surely indices are stored contiguosly */
2460026de310SStefano Zampini         while (total_counts+primal_dofs < pcbddc->local_primal_size && temp_indices_to_constraint_B[temp_indices[total_counts]] == temp_indices_to_constraint_B[temp_indices[total_counts+primal_dofs]]) {
2461026de310SStefano Zampini           primal_dofs++;
2462674ae819SStefano Zampini         }
2463984c4197SStefano Zampini         /* get constraint info */
2464026de310SStefano Zampini         size_of_constraint = temp_indices[total_counts+1]-temp_indices[total_counts];
2465984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
2466984c4197SStefano Zampini 
2467984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2468a717540cSStefano 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);
2469674ae819SStefano Zampini         }
2470984c4197SStefano Zampini 
2471fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
2472a717540cSStefano Zampini 
2473a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
2474a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
2475a717540cSStefano Zampini             ierr = PetscMemcpy(work,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2476a717540cSStefano Zampini           }
2477984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
2478026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2479984c4197SStefano Zampini 
2480984c4197SStefano Zampini           /* compute QR decomposition of constraints */
24813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
24823f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
24833f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2484674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
24853f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
2486984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
2487674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2488984c4197SStefano Zampini 
2489984c4197SStefano Zampini           /* explictly compute R^-T */
2490984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
2491984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
24923f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
24933f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
24943f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
24953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
2496984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
24973f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
2498984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
2499984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2500984c4197SStefano Zampini 
2501a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
25023f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
25033f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
25043f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
25053f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2506984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
25073f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
2508984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
2509984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2510984c4197SStefano Zampini 
2511984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
2512984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
2513984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
25143f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
25153f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
25163f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
25173f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
25183f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
25193f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2520984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2521c4303822SStefano 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));
2522984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2523026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2524984c4197SStefano Zampini 
2525984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
2526026de310SStefano Zampini           start_rows = &temp_indices_to_constraint_B[temp_indices[total_counts]];
2527984c4197SStefano Zampini           /* insert cols for primal dofs */
2528984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
2529984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
2530026de310SStefano Zampini             start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter+j]];
2531906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2532984c4197SStefano Zampini           }
2533984c4197SStefano Zampini           /* insert cols for dual dofs */
2534984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
25354641a718SStefano Zampini             if (!PetscBTLookup(is_primal,temp_indices_to_constraint_B[temp_indices[total_counts]+k])) {
2536984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
2537026de310SStefano Zampini               start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+k];
2538906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2539984c4197SStefano Zampini               j++;
2540674ae819SStefano Zampini             }
2541674ae819SStefano Zampini           }
2542984c4197SStefano Zampini 
2543984c4197SStefano Zampini           /* check change of basis */
2544984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
2545984c4197SStefano Zampini             PetscInt   ii,jj;
2546984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
2547c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
2548c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2549c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
2550c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2551c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
2552c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
2553984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2554c4303822SStefano 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));
2555984c4197SStefano Zampini             ierr = PetscFPTrapPop();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) valid_qr = PETSC_FALSE;
2559984c4197SStefano Zampini                 if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
2560674ae819SStefano Zampini               }
2561674ae819SStefano Zampini             }
2562984c4197SStefano Zampini             if (!valid_qr) {
256322d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
2564984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
2565984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
2566984c4197SStefano Zampini                   if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
2567984c4197SStefano 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]));
2568674ae819SStefano Zampini                   }
2569984c4197SStefano Zampini                   if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
2570984c4197SStefano 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]));
2571984c4197SStefano Zampini                   }
2572984c4197SStefano Zampini                 }
2573984c4197SStefano Zampini               }
2574674ae819SStefano Zampini             } else {
257522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
2576674ae819SStefano Zampini             }
2577674ae819SStefano Zampini           }
2578a717540cSStefano Zampini         } else { /* simple transformation block */
2579a717540cSStefano Zampini           PetscInt    row,col;
2580a6b551f4SStefano Zampini           PetscScalar val,norm;
2581a6b551f4SStefano Zampini 
2582a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2583a6b551f4SStefano 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));
2584a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
2585a717540cSStefano Zampini             row = temp_indices_to_constraint_B[temp_indices[total_counts]+j];
2586a717540cSStefano Zampini             if (!PetscBTLookup(is_primal,row)) {
2587a717540cSStefano Zampini               col = temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2588906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
2589a6b551f4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,temp_quadrature_constraint[temp_indices[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
2590a717540cSStefano Zampini             } else {
2591a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
2592a717540cSStefano Zampini                 col = temp_indices_to_constraint_B[temp_indices[total_counts]+k];
2593a717540cSStefano Zampini                 if (row != col) {
2594a717540cSStefano Zampini                   val = -temp_quadrature_constraint[temp_indices[total_counts]+k]/temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2595a717540cSStefano Zampini                 } else {
2596a6b551f4SStefano Zampini                   val = temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]]/norm;
2597a717540cSStefano Zampini                 }
2598906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
2599a717540cSStefano Zampini               }
2600a717540cSStefano Zampini             }
2601a717540cSStefano Zampini           }
260298a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
260322d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
2604a717540cSStefano Zampini           }
2605674ae819SStefano Zampini         }
2606026de310SStefano Zampini         /* increment primal counter */
2607026de310SStefano Zampini         primal_counter += primal_dofs;
2608984c4197SStefano Zampini       } else {
2609984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2610026de310SStefano 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);
2611674ae819SStefano Zampini         }
2612674ae819SStefano Zampini       }
2613026de310SStefano Zampini       /* increment constraint counter total_counts */
2614026de310SStefano Zampini       total_counts += primal_dofs;
2615674ae819SStefano Zampini     }
2616a717540cSStefano Zampini 
2617a717540cSStefano Zampini     /* free workspace */
2618a717540cSStefano Zampini     if (qr_needed) {
2619984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
2620984c4197SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
2621984c4197SStefano Zampini       }
2622984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
2623984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
2624984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
2625984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
2626984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
2627674ae819SStefano Zampini     }
2628a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
2629906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2630906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2631906d46d4SStefano Zampini 
2632906d46d4SStefano Zampini     /* assembling of global change of variable */
2633906d46d4SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2634906d46d4SStefano Zampini     ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2635906d46d4SStefano Zampini     ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2636906d46d4SStefano Zampini     ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2637906d46d4SStefano Zampini     ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2638906d46d4SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->ChangeOfBasisMatrix,matis->mapping,matis->mapping);CHKERRQ(ierr);
2639906d46d4SStefano Zampini 
2640906d46d4SStefano Zampini     /* nonzeros (overestimated) */
2641906d46d4SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&nnz_vec);CHKERRQ(ierr);
2642906d46d4SStefano Zampini     ierr = VecSetLocalToGlobalMapping(nnz_vec,matis->mapping);CHKERRQ(ierr);
2643906d46d4SStefano Zampini     ierr = PetscMalloc2(pcis->n,&nnz_array,pcis->n,&idxs_all);CHKERRQ(ierr);
2644906d46d4SStefano Zampini     for (i=0;i<pcis->n;i++) {
2645906d46d4SStefano Zampini       nnz_array[i] = 1.0;
2646906d46d4SStefano Zampini       idxs_all[i] = i;
2647906d46d4SStefano Zampini     }
2648906d46d4SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&idxs_B);CHKERRQ(ierr);
2649906d46d4SStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2650906d46d4SStefano Zampini       nnz_array[idxs_B[i]] = nnz[i];
2651906d46d4SStefano Zampini     }
2652a5187659SStefano Zampini     if (pcis->n) {
2653906d46d4SStefano Zampini       ierr = VecSetValuesLocal(nnz_vec,pcis->n,idxs_all,nnz_array,INSERT_VALUES);CHKERRQ(ierr);
2654a5187659SStefano Zampini     }
2655906d46d4SStefano Zampini     ierr = VecAssemblyBegin(nnz_vec);CHKERRQ(ierr);
2656906d46d4SStefano Zampini     ierr = VecAssemblyEnd(nnz_vec);CHKERRQ(ierr);
2657906d46d4SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2658906d46d4SStefano Zampini     ierr = PetscFree2(nnz_array,idxs_all);CHKERRQ(ierr);
265922bc73bbSStefano Zampini     ierr = PetscMalloc2(local_size,&d_nnz,local_size,&o_nnz);CHKERRQ(ierr);
2660906d46d4SStefano Zampini     ierr = VecGetArray(nnz_vec,&nnz_array);CHKERRQ(ierr);
2661906d46d4SStefano Zampini     for (i=0;i<local_size;i++) {
266222bc73bbSStefano Zampini       d_nnz[i] = PetscMin((PetscInt)(PetscRealPart(nnz_array[i])),local_size);
266322bc73bbSStefano Zampini       o_nnz[i] = PetscMin((PetscInt)(PetscRealPart(nnz_array[i])),global_size-local_size);
2664906d46d4SStefano Zampini     }
2665906d46d4SStefano Zampini     ierr = VecRestoreArray(nnz_vec,&nnz_array);CHKERRQ(ierr);
2666906d46d4SStefano Zampini     ierr = VecDestroy(&nnz_vec);CHKERRQ(ierr);
266722bc73bbSStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->ChangeOfBasisMatrix,0,d_nnz,0,o_nnz);CHKERRQ(ierr);
266822bc73bbSStefano Zampini     ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr);
2669906d46d4SStefano Zampini 
2670906d46d4SStefano Zampini     /* Set identity on dirichlet dofs */
2671906d46d4SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idxs_I);CHKERRQ(ierr);
2672906d46d4SStefano Zampini     for (i=0;i<pcis->n-pcis->n_B;i++) {
2673906d46d4SStefano Zampini       PetscScalar one=1.0;
2674906d46d4SStefano Zampini       ierr = MatSetValuesLocal(pcbddc->ChangeOfBasisMatrix,1,idxs_I+i,1,idxs_I+i,&one,INSERT_VALUES);CHKERRQ(ierr);
2675906d46d4SStefano Zampini     }
2676906d46d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idxs_I);CHKERRQ(ierr);
2677906d46d4SStefano Zampini 
2678906d46d4SStefano Zampini     /* Set values at interface dofs */
2679906d46d4SStefano Zampini     done = PETSC_TRUE;
2680906d46d4SStefano Zampini     ierr = MatGetRowIJ(localChangeOfBasisMatrix,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2681906d46d4SStefano Zampini     if (!done) {
2682906d46d4SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2683906d46d4SStefano Zampini     }
2684906d46d4SStefano Zampini     ierr = MatSeqAIJGetArray(localChangeOfBasisMatrix,&vals);CHKERRQ(ierr);
2685906d46d4SStefano Zampini     ierr = PetscMalloc1(xadj[nvtxs],&idxs_mapped);CHKERRQ(ierr);
26865e8657edSStefano Zampini     ierr = ISLocalToGlobalMappingApply(pcis->BtoNmap,xadj[nvtxs],adjncy,idxs_mapped);CHKERRQ(ierr);
2687906d46d4SStefano Zampini     for (i=0;i<nvtxs;i++) {
2688906d46d4SStefano Zampini       PetscInt    row,*cols,ncols;
2689906d46d4SStefano Zampini       PetscScalar *mat_vals;
2690906d46d4SStefano Zampini 
2691906d46d4SStefano Zampini       row = idxs_B[i];
2692906d46d4SStefano Zampini       ncols = xadj[i+1]-xadj[i];
2693906d46d4SStefano Zampini       cols = idxs_mapped+xadj[i];
2694906d46d4SStefano Zampini       mat_vals = vals+xadj[i];
2695906d46d4SStefano Zampini       ierr = MatSetValuesLocal(pcbddc->ChangeOfBasisMatrix,1,&row,ncols,cols,mat_vals,INSERT_VALUES);CHKERRQ(ierr);
2696906d46d4SStefano Zampini     }
2697906d46d4SStefano Zampini     ierr = MatRestoreRowIJ(localChangeOfBasisMatrix,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2698906d46d4SStefano Zampini     if (!done) {
2699906d46d4SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2700906d46d4SStefano Zampini     }
2701906d46d4SStefano Zampini     ierr = MatSeqAIJRestoreArray(localChangeOfBasisMatrix,&vals);CHKERRQ(ierr);
2702906d46d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&idxs_B);CHKERRQ(ierr);
2703906d46d4SStefano Zampini     ierr = PetscFree(idxs_mapped);CHKERRQ(ierr);
2704674ae819SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2705674ae819SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2706906d46d4SStefano Zampini 
2707906d46d4SStefano Zampini     /* check */
2708906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
2709906d46d4SStefano Zampini       PetscReal error;
2710906d46d4SStefano Zampini       Vec       x,x_change;
2711906d46d4SStefano Zampini 
2712906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
2713906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
2714906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2715906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
2716906d46d4SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2717906d46d4SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2718906d46d4SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
2719906d46d4SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2720906d46d4SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2721906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
2722906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2723906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2724906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2725906d46d4SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on B: %1.6e\n",error);CHKERRQ(ierr);
2726906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
2727906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2728906d46d4SStefano Zampini     }
2729b96c3477SStefano Zampini 
2730b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
2731b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
2732b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
2733b96c3477SStefano Zampini       if (sub_schurs->n_subs_par_g) {
2734b7eb3628SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Change of basis with deluxe scaling and parallel problems still needs to be implemented");
2735b96c3477SStefano Zampini       }
2736b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
2737b96c3477SStefano Zampini         Mat S_1,S_2,tmat;
2738b96c3477SStefano Zampini         ierr = MatGetSubMatrixUnsorted(localChangeOfBasisMatrix,sub_schurs->is_Ej_all,sub_schurs->is_Ej_all,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
2739b96c3477SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_1);CHKERRQ(ierr);
2740b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
2741b96c3477SStefano Zampini         sub_schurs->S_Ej_all = S_1;
2742b96c3477SStefano Zampini         ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_2);CHKERRQ(ierr);
2743b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
2744b96c3477SStefano Zampini         sub_schurs->sum_S_Ej_all = S_2;
2745b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2746b96c3477SStefano Zampini       }
2747b96c3477SStefano Zampini     }
2748906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
2749906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
2750b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2751b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
2752b9b85e73SStefano Zampini   }
2753906d46d4SStefano Zampini 
2754906d46d4SStefano Zampini   /* set up change of basis context */
2755906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2756906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
2757906d46d4SStefano Zampini 
2758906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
2759906d46d4SStefano Zampini       PetscInt global_size,local_size;
2760906d46d4SStefano Zampini 
2761906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2762906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2763906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
2764906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2765906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
2766906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
2767906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
2768906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
2769906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
2770906d46d4SStefano Zampini     } else {
2771906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
2772906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
2773906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
2774906d46d4SStefano Zampini     }
2775906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
2776906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2777906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
2778906d46d4SStefano Zampini     } else {
2779906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2780906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
2781906d46d4SStefano Zampini     }
2782906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
2783906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
2784906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2785906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2786b9b85e73SStefano Zampini   }
2787a717540cSStefano Zampini 
2788727cdba6SStefano Zampini   /* get indices in local ordering for vertices and constraints */
2789727cdba6SStefano 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 */
2790473ba861SJed Brown     ierr = PetscMalloc1(olocal_primal_size,&oprimal_indices_local_idxs);CHKERRQ(ierr);
2791727cdba6SStefano Zampini     ierr = PetscMemcpy(oprimal_indices_local_idxs,pcbddc->primal_indices_local_idxs,olocal_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2792727cdba6SStefano Zampini   }
2793727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2794f347579bSStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2795473ba861SJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2796727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_primal_numbering);CHKERRQ(ierr);
2797727cdba6SStefano Zampini   ierr = PetscMemcpy(pcbddc->primal_indices_local_idxs,aux_primal_numbering,i*sizeof(PetscInt));CHKERRQ(ierr);
2798727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2799727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_primal_numbering);CHKERRQ(ierr);
2800727cdba6SStefano Zampini   ierr = PetscMemcpy(&pcbddc->primal_indices_local_idxs[i],aux_primal_numbering,j*sizeof(PetscInt));CHKERRQ(ierr);
2801727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2802e9189074SStefano Zampini   /* set quantities in PCBDDC data struct */
2803e9189074SStefano Zampini   pcbddc->n_actual_vertices = i;
2804727cdba6SStefano Zampini   /* check if a new primal space has been introduced */
2805727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
2806727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
2807727cdba6SStefano Zampini     ierr = PetscMemcmp(pcbddc->primal_indices_local_idxs,oprimal_indices_local_idxs,olocal_primal_size,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
2808c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
2809727cdba6SStefano Zampini     ierr = PetscFree(oprimal_indices_local_idxs);CHKERRQ(ierr);
2810727cdba6SStefano Zampini   }
2811727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
2812727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2813727cdba6SStefano Zampini 
2814a717540cSStefano Zampini   /* flush dbg viewer */
2815b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
2816b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2817b8ffe317SStefano Zampini   }
2818a717540cSStefano Zampini 
2819e310c8b4SStefano Zampini   /* free workspace */
2820a717540cSStefano Zampini   ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2821a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
2822984c4197SStefano Zampini   ierr = PetscFree(aux_primal_minloc);CHKERRQ(ierr);
28234641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
282408122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
2825906d46d4SStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
2826906d46d4SStefano Zampini     ierr = PetscFree3(temp_quadrature_constraint,temp_indices_to_constraint,temp_indices_to_constraint_B);CHKERRQ(ierr);
282708122e43SStefano Zampini   } else {
282808122e43SStefano Zampini     ierr = PetscFree4(pcbddc->adaptive_constraints_n,
282908122e43SStefano Zampini                       pcbddc->adaptive_constraints_ptrs,
283008122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
283108122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
283208122e43SStefano Zampini     ierr = PetscFree(temp_indices_to_constraint_B);CHKERRQ(ierr);
283308122e43SStefano Zampini   }
2834674ae819SStefano Zampini   PetscFunctionReturn(0);
2835674ae819SStefano Zampini }
2836674ae819SStefano Zampini 
2837674ae819SStefano Zampini #undef __FUNCT__
2838674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
2839674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
2840674ae819SStefano Zampini {
2841674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
2842674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
2843674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
284463602bcaSStefano Zampini   PetscInt    ierr,i,vertex_size;
2845674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
2846674ae819SStefano Zampini 
2847674ae819SStefano Zampini   PetscFunctionBegin;
28488e61c736SStefano Zampini   /* Reset previously computed graph */
28498e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
2850674ae819SStefano Zampini   /* Init local Graph struct */
2851674ae819SStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,matis->mapping);CHKERRQ(ierr);
2852674ae819SStefano Zampini 
2853575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
2854575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
2855575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2856575ad6abSStefano Zampini   }
28579577ea80SStefano Zampini 
2858674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
28594d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
2860674ae819SStefano Zampini     Mat       mat_adj;
28614d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
28624d379d7bSStefano Zampini     PetscInt  nvtxs;
2863674ae819SStefano Zampini     PetscBool flg_row=PETSC_TRUE;
2864674ae819SStefano Zampini 
2865674ae819SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
28664d379d7bSStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2867674ae819SStefano Zampini     if (!flg_row) {
2868674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2869674ae819SStefano Zampini     }
28704d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
28714d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
2872b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
28734d379d7bSStefano Zampini     } else { /* just compute subdomain's connected components */
28744d379d7bSStefano Zampini       IS                     is_dummy;
28754d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
28764d379d7bSStefano Zampini       PetscInt               j,sum;
28774d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
28784d379d7bSStefano Zampini       const PetscInt         *idxs;
28794d379d7bSStefano Zampini       PCBDDCGraph            graph;
28804d379d7bSStefano Zampini       PetscBT                is_on_boundary;
28814d379d7bSStefano Zampini 
28824d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
28834d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
28844d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
28854d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
28864d379d7bSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy);CHKERRQ(ierr);
28874d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
28884d379d7bSStefano Zampini       graph->xadj = xadj;
28894d379d7bSStefano Zampini       graph->adjncy = adjncy;
28904d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
28914d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
28924d379d7bSStefano Zampini 
28934d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
28944d379d7bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains\n",PetscGlobalRank,graph->ncc);CHKERRQ(ierr);
28954d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
28964d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
28974d379d7bSStefano Zampini         }
28984d379d7bSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
28994d379d7bSStefano Zampini       }
29004d379d7bSStefano Zampini 
29014d379d7bSStefano Zampini       ierr = PetscBTCreate(nvtxs,&is_on_boundary);CHKERRQ(ierr);
29024d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
29034d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
29044d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
29054d379d7bSStefano Zampini       }
29064d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
29074d379d7bSStefano Zampini 
29084d379d7bSStefano Zampini       ierr = PetscCalloc1(nvtxs+1,&cxadj);CHKERRQ(ierr);
29094d379d7bSStefano Zampini       sum = 0;
29104d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
29114d379d7bSStefano Zampini         PetscInt sizecc = 0;
29124d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
29134d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
29144d379d7bSStefano Zampini             sizecc++;
29154d379d7bSStefano Zampini           }
29164d379d7bSStefano Zampini         }
29174d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
29184d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
29194d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
29204d379d7bSStefano Zampini           }
29214d379d7bSStefano Zampini         }
29224d379d7bSStefano Zampini         sum += sizecc*sizecc;
29234d379d7bSStefano Zampini       }
29244d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
29254d379d7bSStefano Zampini       sum = 0;
29264d379d7bSStefano Zampini       for (i=0;i<nvtxs;i++) {
29274d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
29284d379d7bSStefano Zampini         cxadj[i] = sum;
29294d379d7bSStefano Zampini         sum += temp;
29304d379d7bSStefano Zampini       }
29314d379d7bSStefano Zampini       cxadj[nvtxs] = sum;
29324d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
29334d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
29344d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
29354d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
29364d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
29374d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
29384d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
29394d379d7bSStefano Zampini                 sizecc++;
29404d379d7bSStefano Zampini               }
29414d379d7bSStefano Zampini             }
29424d379d7bSStefano Zampini           }
29434d379d7bSStefano Zampini         }
29444d379d7bSStefano Zampini       }
29454d379d7bSStefano Zampini       if (nvtxs) {
29464d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
29474d379d7bSStefano Zampini       } else {
29484d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
29494d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
29504d379d7bSStefano Zampini       }
29514d379d7bSStefano Zampini       graph->xadj = 0;
29524d379d7bSStefano Zampini       graph->adjncy = 0;
29534d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
29544d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
29554d379d7bSStefano Zampini     }
29564d379d7bSStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2957674ae819SStefano Zampini     if (!flg_row) {
2958674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2959674ae819SStefano Zampini     }
2960674ae819SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2961674ae819SStefano Zampini   }
2962674ae819SStefano Zampini 
296363602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
2964674ae819SStefano Zampini   vertex_size = 1;
296563602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
296663602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
296795ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
296863602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
2969a7dc3881SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
297063602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2971674ae819SStefano Zampini       }
297263602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
297363602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
297463602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
2975674ae819SStefano Zampini     }
297663602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
2977674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
297863602bcaSStefano Zampini   } else {
297963602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
298063602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
2981854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
298263602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
298363602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
298463602bcaSStefano Zampini       }
298563602bcaSStefano Zampini     }
2986674ae819SStefano Zampini   }
2987674ae819SStefano Zampini 
2988674ae819SStefano Zampini   /* Setup of Graph */
2989785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
2990a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
2991785d1243SStefano Zampini   }
2992785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
2993a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2994785d1243SStefano Zampini   }
299563602bcaSStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);
2996674ae819SStefano Zampini 
2997674ae819SStefano Zampini   /* Graph's connected components analysis */
2998674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
2999674ae819SStefano Zampini 
3000674ae819SStefano Zampini   /* print some info to stdout */
3001674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3002e49050b4SStefano Zampini     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);
3003674ae819SStefano Zampini   }
3004fb180af4SStefano Zampini 
3005fb180af4SStefano Zampini   /* mark topography has done */
3006fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3007674ae819SStefano Zampini   PetscFunctionReturn(0);
3008674ae819SStefano Zampini }
3009674ae819SStefano Zampini 
3010674ae819SStefano Zampini #undef __FUNCT__
3011674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalVerticesLocalIdx"
3012f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalVerticesLocalIdx(PC pc, PetscInt *n_vertices, PetscInt **vertices_idx)
3013674ae819SStefano Zampini {
3014674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
3015674ae819SStefano Zampini   PetscInt       *vertices,*row_cmat_indices,n,i,size_of_constraint,local_primal_size;
3016674ae819SStefano Zampini   PetscErrorCode ierr;
3017674ae819SStefano Zampini 
3018674ae819SStefano Zampini   PetscFunctionBegin;
3019674ae819SStefano Zampini   n = 0;
3020674ae819SStefano Zampini   vertices = 0;
3021674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
3022674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&i);CHKERRQ(ierr);
3023b120a5c6SStefano Zampini     for (i=0;i<local_primal_size;i++) {
3024b120a5c6SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
3025b120a5c6SStefano Zampini       if (size_of_constraint == 1) n++;
3026b120a5c6SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
3027b120a5c6SStefano Zampini     }
3028811e8ca2SStefano Zampini     if (vertices_idx) {
3029785e854fSJed Brown       ierr = PetscMalloc1(n,&vertices);CHKERRQ(ierr);
3030b120a5c6SStefano Zampini       n = 0;
3031674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
3032674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
3033674ae819SStefano Zampini         if (size_of_constraint == 1) {
3034674ae819SStefano Zampini           vertices[n++]=row_cmat_indices[0];
3035674ae819SStefano Zampini         }
3036674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
3037674ae819SStefano Zampini       }
3038674ae819SStefano Zampini     }
3039811e8ca2SStefano Zampini   }
3040674ae819SStefano Zampini   *n_vertices = n;
3041811e8ca2SStefano Zampini   if (vertices_idx) *vertices_idx = vertices;
3042674ae819SStefano Zampini   PetscFunctionReturn(0);
3043674ae819SStefano Zampini }
3044674ae819SStefano Zampini 
3045674ae819SStefano Zampini #undef __FUNCT__
3046674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalConstraintsLocalIdx"
3047f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalConstraintsLocalIdx(PC pc, PetscInt *n_constraints, PetscInt **constraints_idx)
3048674ae819SStefano Zampini {
3049674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
3050674ae819SStefano Zampini   PetscInt       *constraints_index,*row_cmat_indices,*row_cmat_global_indices;
3051674ae819SStefano Zampini   PetscInt       n,i,j,size_of_constraint,local_primal_size,local_size,max_size_of_constraint,min_index,min_loc;
30524641a718SStefano Zampini   PetscBT        touched;
3053674ae819SStefano Zampini   PetscErrorCode ierr;
3054674ae819SStefano Zampini 
3055f34684f1SStefano Zampini     /* This function assumes that the number of local constraints per connected component
3056f34684f1SStefano Zampini        is not greater than the number of nodes defined for the connected component
3057f34684f1SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
3058674ae819SStefano Zampini   PetscFunctionBegin;
3059674ae819SStefano Zampini   n = 0;
3060674ae819SStefano Zampini   constraints_index = 0;
3061674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
3062674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&local_size);CHKERRQ(ierr);
3063674ae819SStefano Zampini     max_size_of_constraint = 0;
3064674ae819SStefano Zampini     for (i=0;i<local_primal_size;i++) {
3065674ae819SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
3066674ae819SStefano Zampini       if (size_of_constraint > 1) {
3067674ae819SStefano Zampini         n++;
3068674ae819SStefano Zampini       }
3069674ae819SStefano Zampini       max_size_of_constraint = PetscMax(size_of_constraint,max_size_of_constraint);
3070674ae819SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
3071674ae819SStefano Zampini     }
3072811e8ca2SStefano Zampini     if (constraints_idx) {
3073785e854fSJed Brown       ierr = PetscMalloc1(n,&constraints_index);CHKERRQ(ierr);
3074785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint,&row_cmat_global_indices);CHKERRQ(ierr);
30754641a718SStefano Zampini       ierr = PetscBTCreate(local_size,&touched);CHKERRQ(ierr);
3076674ae819SStefano Zampini       n = 0;
3077674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
3078674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
3079674ae819SStefano Zampini         if (size_of_constraint > 1) {
3080674ae819SStefano Zampini           ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
308182d3d8afSStefano Zampini           /* find first untouched local node */
308282d3d8afSStefano Zampini           j = 0;
30834641a718SStefano Zampini           while (PetscBTLookup(touched,row_cmat_indices[j])) j++;
308482d3d8afSStefano Zampini           min_index = row_cmat_global_indices[j];
308582d3d8afSStefano Zampini           min_loc = j;
308682d3d8afSStefano Zampini           /* search the minimum among nodes not yet touched on the connected component
308782d3d8afSStefano Zampini              since there can be more than one constraint on a single cc */
3088674ae819SStefano Zampini           for (j=1;j<size_of_constraint;j++) {
30894641a718SStefano Zampini             if (!PetscBTLookup(touched,row_cmat_indices[j]) && min_index > row_cmat_global_indices[j]) {
3090674ae819SStefano Zampini               min_index = row_cmat_global_indices[j];
3091674ae819SStefano Zampini               min_loc = j;
3092674ae819SStefano Zampini             }
3093674ae819SStefano Zampini           }
30944641a718SStefano Zampini           ierr = PetscBTSet(touched,row_cmat_indices[min_loc]);CHKERRQ(ierr);
3095674ae819SStefano Zampini           constraints_index[n++] = row_cmat_indices[min_loc];
3096674ae819SStefano Zampini         }
3097674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
3098674ae819SStefano Zampini       }
30994641a718SStefano Zampini       ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
3100674ae819SStefano Zampini       ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
3101811e8ca2SStefano Zampini     }
3102811e8ca2SStefano Zampini   }
3103674ae819SStefano Zampini   *n_constraints = n;
3104811e8ca2SStefano Zampini   if (constraints_idx) *constraints_idx = constraints_index;
3105674ae819SStefano Zampini   PetscFunctionReturn(0);
3106674ae819SStefano Zampini }
3107674ae819SStefano Zampini 
3108674ae819SStefano Zampini #undef __FUNCT__
3109674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3110674ae819SStefano 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[])
3111674ae819SStefano Zampini {
3112674ae819SStefano Zampini   Vec            local_vec,global_vec;
3113674ae819SStefano Zampini   IS             seqis,paris;
3114674ae819SStefano Zampini   VecScatter     scatter_ctx;
3115674ae819SStefano Zampini   PetscScalar    *array;
3116674ae819SStefano Zampini   PetscInt       *temp_global_dofs;
3117674ae819SStefano Zampini   PetscScalar    globalsum;
3118674ae819SStefano Zampini   PetscInt       i,j,s;
3119674ae819SStefano Zampini   PetscInt       nlocals,first_index,old_index,max_local;
3120674ae819SStefano Zampini   PetscMPIInt    rank_prec_comm,size_prec_comm,max_global;
3121674ae819SStefano Zampini   PetscMPIInt    *dof_sizes,*dof_displs;
3122674ae819SStefano Zampini   PetscBool      first_found;
3123674ae819SStefano Zampini   PetscErrorCode ierr;
3124674ae819SStefano Zampini 
3125674ae819SStefano Zampini   PetscFunctionBegin;
3126674ae819SStefano Zampini   /* mpi buffers */
3127b9b85e73SStefano Zampini   ierr = MPI_Comm_size(comm,&size_prec_comm);CHKERRQ(ierr);
3128b9b85e73SStefano Zampini   ierr = MPI_Comm_rank(comm,&rank_prec_comm);CHKERRQ(ierr);
3129674ae819SStefano Zampini   j = ( !rank_prec_comm ? size_prec_comm : 0);
3130785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_sizes);CHKERRQ(ierr);
3131785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_displs);CHKERRQ(ierr);
3132674ae819SStefano Zampini   /* get maximum size of subset */
3133785e854fSJed Brown   ierr = PetscMalloc1(n_local_dofs,&temp_global_dofs);CHKERRQ(ierr);
3134674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingApply(l2gmap,n_local_dofs,local_dofs,temp_global_dofs);CHKERRQ(ierr);
3135674ae819SStefano Zampini   max_local = 0;
3136b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
3137674ae819SStefano Zampini     if (max_local < temp_global_dofs[i] ) {
3138674ae819SStefano Zampini       max_local = temp_global_dofs[i];
3139674ae819SStefano Zampini     }
3140674ae819SStefano Zampini   }
3141b9b85e73SStefano Zampini   ierr = MPI_Allreduce(&max_local,&max_global,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
3142674ae819SStefano Zampini   max_global++;
3143674ae819SStefano Zampini   max_local = 0;
3144b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
3145674ae819SStefano Zampini     if (max_local < local_dofs[i] ) {
3146674ae819SStefano Zampini       max_local = local_dofs[i];
3147674ae819SStefano Zampini     }
3148674ae819SStefano Zampini   }
3149674ae819SStefano Zampini   max_local++;
3150674ae819SStefano Zampini   /* allocate workspace */
3151674ae819SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&local_vec);CHKERRQ(ierr);
3152674ae819SStefano Zampini   ierr = VecSetSizes(local_vec,PETSC_DECIDE,max_local);CHKERRQ(ierr);
3153674ae819SStefano Zampini   ierr = VecSetType(local_vec,VECSEQ);CHKERRQ(ierr);
3154674ae819SStefano Zampini   ierr = VecCreate(comm,&global_vec);CHKERRQ(ierr);
3155674ae819SStefano Zampini   ierr = VecSetSizes(global_vec,PETSC_DECIDE,max_global);CHKERRQ(ierr);
3156674ae819SStefano Zampini   ierr = VecSetType(global_vec,VECMPI);CHKERRQ(ierr);
3157674ae819SStefano Zampini   /* create scatter */
3158674ae819SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_local_dofs,local_dofs,PETSC_COPY_VALUES,&seqis);CHKERRQ(ierr);
3159674ae819SStefano Zampini   ierr = ISCreateGeneral(comm,n_local_dofs,temp_global_dofs,PETSC_COPY_VALUES,&paris);CHKERRQ(ierr);
3160674ae819SStefano Zampini   ierr = VecScatterCreate(local_vec,seqis,global_vec,paris,&scatter_ctx);CHKERRQ(ierr);
3161674ae819SStefano Zampini   ierr = ISDestroy(&seqis);CHKERRQ(ierr);
3162674ae819SStefano Zampini   ierr = ISDestroy(&paris);CHKERRQ(ierr);
3163674ae819SStefano Zampini   /* init array */
3164674ae819SStefano Zampini   ierr = VecSet(global_vec,0.0);CHKERRQ(ierr);
3165674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
3166674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
3167674ae819SStefano Zampini   if (local_dofs_mult) {
3168674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
3169674ae819SStefano Zampini       array[local_dofs[i]]=(PetscScalar)local_dofs_mult[i];
3170674ae819SStefano Zampini     }
3171674ae819SStefano Zampini   } else {
3172674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
3173674ae819SStefano Zampini       array[local_dofs[i]]=1.0;
3174674ae819SStefano Zampini     }
3175674ae819SStefano Zampini   }
3176674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
3177674ae819SStefano Zampini   /* scatter into global vec and get total number of global dofs */
3178674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3179674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3180674ae819SStefano Zampini   ierr = VecSum(global_vec,&globalsum);CHKERRQ(ierr);
31815b08dc53SStefano Zampini   *n_global_subset = (PetscInt)PetscRealPart(globalsum);
3182674ae819SStefano Zampini   /* Fill global_vec with cumulative function for global numbering */
3183674ae819SStefano Zampini   ierr = VecGetArray(global_vec,&array);CHKERRQ(ierr);
3184674ae819SStefano Zampini   ierr = VecGetLocalSize(global_vec,&s);CHKERRQ(ierr);
3185674ae819SStefano Zampini   nlocals = 0;
3186674ae819SStefano Zampini   first_index = -1;
3187674ae819SStefano Zampini   first_found = PETSC_FALSE;
3188674ae819SStefano Zampini   for (i=0;i<s;i++) {
3189b9b85e73SStefano Zampini     if (!first_found && PetscRealPart(array[i]) > 0.1) {
3190674ae819SStefano Zampini       first_found = PETSC_TRUE;
3191674ae819SStefano Zampini       first_index = i;
3192674ae819SStefano Zampini     }
31935b08dc53SStefano Zampini     nlocals += (PetscInt)PetscRealPart(array[i]);
3194674ae819SStefano Zampini   }
3195674ae819SStefano Zampini   ierr = MPI_Gather(&nlocals,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
3196674ae819SStefano Zampini   if (!rank_prec_comm) {
3197674ae819SStefano Zampini     dof_displs[0]=0;
3198674ae819SStefano Zampini     for (i=1;i<size_prec_comm;i++) {
3199674ae819SStefano Zampini       dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
3200674ae819SStefano Zampini     }
3201674ae819SStefano Zampini   }
3202674ae819SStefano Zampini   ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&nlocals,1,MPIU_INT,0,comm);CHKERRQ(ierr);
3203674ae819SStefano Zampini   if (first_found) {
3204674ae819SStefano Zampini     array[first_index] += (PetscScalar)nlocals;
3205674ae819SStefano Zampini     old_index = first_index;
3206674ae819SStefano Zampini     for (i=first_index+1;i<s;i++) {
3207b9b85e73SStefano Zampini       if (PetscRealPart(array[i]) > 0.1) {
3208674ae819SStefano Zampini         array[i] += array[old_index];
3209674ae819SStefano Zampini         old_index = i;
3210674ae819SStefano Zampini       }
3211674ae819SStefano Zampini     }
3212674ae819SStefano Zampini   }
3213674ae819SStefano Zampini   ierr = VecRestoreArray(global_vec,&array);CHKERRQ(ierr);
3214674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
3215674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3216674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3217674ae819SStefano Zampini   /* get global ordering of local dofs */
3218674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
3219674ae819SStefano Zampini   if (local_dofs_mult) {
3220674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
32215b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-local_dofs_mult[i];
3222674ae819SStefano Zampini     }
3223674ae819SStefano Zampini   } else {
3224674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
32255b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-1;
3226674ae819SStefano Zampini     }
3227674ae819SStefano Zampini   }
3228674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
3229674ae819SStefano Zampini   /* free workspace */
3230674ae819SStefano Zampini   ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
3231674ae819SStefano Zampini   ierr = VecDestroy(&local_vec);CHKERRQ(ierr);
3232674ae819SStefano Zampini   ierr = VecDestroy(&global_vec);CHKERRQ(ierr);
3233674ae819SStefano Zampini   ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
3234674ae819SStefano Zampini   ierr = PetscFree(dof_displs);CHKERRQ(ierr);
3235674ae819SStefano Zampini   /* return pointer to global ordering of local dofs */
3236674ae819SStefano Zampini   *global_numbering_subset = temp_global_dofs;
3237674ae819SStefano Zampini   PetscFunctionReturn(0);
3238674ae819SStefano Zampini }
32399a7d3425SStefano Zampini 
32409a7d3425SStefano Zampini #undef __FUNCT__
32419a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
32429a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
32439a7d3425SStefano Zampini {
32449a7d3425SStefano Zampini   PetscInt       i,j;
32459a7d3425SStefano Zampini   PetscScalar    *alphas;
32469a7d3425SStefano Zampini   PetscErrorCode ierr;
32479a7d3425SStefano Zampini 
32489a7d3425SStefano Zampini   PetscFunctionBegin;
32499a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
3250785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
32519a7d3425SStefano Zampini   for (i=0;i<n;i++) {
32529a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
32539a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
32549a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
32559a7d3425SStefano Zampini   }
32569a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
32579a7d3425SStefano Zampini   PetscFunctionReturn(0);
32589a7d3425SStefano Zampini }
32599a7d3425SStefano Zampini 
3260e7931f94SStefano Zampini #undef __FUNCT__
326170cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
326228143c3dSStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscBool contiguous, IS* is_sends)
3263e7931f94SStefano Zampini {
3264e7931f94SStefano Zampini   Mat             subdomain_adj;
3265e7931f94SStefano Zampini   IS              new_ranks,ranks_send_to;
3266e7931f94SStefano Zampini   MatPartitioning partitioner;
3267e7931f94SStefano Zampini   Mat_IS          *matis;
3268e7931f94SStefano Zampini   PetscInt        n_neighs,*neighs,*n_shared,**shared;
3269e7931f94SStefano Zampini   PetscInt        prank;
3270e7931f94SStefano Zampini   PetscMPIInt     size,rank,color;
3271e7931f94SStefano Zampini   PetscInt        *xadj,*adjncy,*oldranks;
3272e7931f94SStefano Zampini   PetscInt        *adjncy_wgt,*v_wgt,*is_indices,*ranks_send_to_idx;
32733837a79fSStefano Zampini   PetscInt        i,local_size,threshold=0;
3274e7931f94SStefano Zampini   PetscErrorCode  ierr;
32752b510759SStefano Zampini   PetscBool       use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
3276e7931f94SStefano Zampini   PetscSubcomm    subcomm;
3277a57a6d2fSStefano Zampini 
3278e7931f94SStefano Zampini   PetscFunctionBegin;
32792b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
32802b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
32812b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
3282e7931f94SStefano Zampini 
3283e7931f94SStefano Zampini   /* Get info on mapping */
3284e7931f94SStefano Zampini   matis = (Mat_IS*)(mat->data);
3285e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&local_size);CHKERRQ(ierr);
3286e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3287e7931f94SStefano Zampini 
3288e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
3289785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
3290e7931f94SStefano Zampini   xadj[0] = 0;
3291e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
3292785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
3293785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
3294e7931f94SStefano Zampini 
32952b510759SStefano Zampini   if (threshold) {
3296d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
32972b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3298d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3299d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3300d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3301d023bfaeSStefano Zampini         xadj_count++;
3302e7931f94SStefano Zampini       }
3303e7931f94SStefano Zampini     }
3304d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3305c8587f34SStefano Zampini   } else {
3306e7931f94SStefano Zampini     if (xadj[1]) {
3307e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3308e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3309c8587f34SStefano Zampini     }
3310e7931f94SStefano Zampini   }
3311e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3312e7931f94SStefano Zampini   if (use_square) {
3313e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3314e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3315e7931f94SStefano Zampini     }
3316e7931f94SStefano Zampini   }
3317e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3318e7931f94SStefano Zampini 
33193837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3320e7931f94SStefano Zampini 
3321e7931f94SStefano Zampini   /*
3322e7931f94SStefano Zampini     Restrict work on active processes only.
3323e7931f94SStefano Zampini   */
3324e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3325e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3326e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
33272b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3328d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3329e7931f94SStefano Zampini   if (color) {
3330e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3331e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3332e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3333c8587f34SStefano Zampini   } else {
333428143c3dSStefano Zampini     PetscInt coarsening_ratio;
3335e7931f94SStefano Zampini     ierr = MPI_Comm_size(subcomm->comm,&size);CHKERRQ(ierr);
3336785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3337e7931f94SStefano Zampini     prank = rank;
3338e7931f94SStefano Zampini     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm->comm);CHKERRQ(ierr);
33398002ef2cSStefano Zampini     /*
3340e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3341e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3342c8587f34SStefano Zampini     }
33438002ef2cSStefano Zampini     */
3344e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3345e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3346c8587f34SStefano Zampini     }
3347e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3348e7931f94SStefano Zampini     ierr = MatCreateMPIAdj(subcomm->comm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
334922b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3350e7931f94SStefano Zampini 
3351e7931f94SStefano Zampini     /* Partition */
3352e7931f94SStefano Zampini     ierr = MatPartitioningCreate(subcomm->comm,&partitioner);CHKERRQ(ierr);
3353e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3354e7931f94SStefano Zampini     if (use_vwgt) {
33553837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3356e7931f94SStefano Zampini       v_wgt[0] = local_size;
3357e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3358c8587f34SStefano Zampini     }
335928143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
336028143c3dSStefano Zampini     coarsening_ratio = size/n_subdomains;
336128143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3362e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3363e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
336422b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3365e7931f94SStefano Zampini 
3366e7931f94SStefano Zampini     ierr = ISGetIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
336728143c3dSStefano Zampini     if (contiguous) {
336828143c3dSStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]]; /* contiguos set of processes */
336928143c3dSStefano Zampini     } else {
337084ba6060SStefano Zampini       ranks_send_to_idx[0] = coarsening_ratio*oldranks[is_indices[0]]; /* scattered set of processes */
337128143c3dSStefano Zampini     }
3372e7931f94SStefano Zampini     ierr = ISRestoreIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3373e7931f94SStefano Zampini     /* clean up */
3374e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
3375e7931f94SStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
3376e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3377e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3378e7931f94SStefano Zampini   }
3379e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3380e7931f94SStefano Zampini 
3381e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3382e7931f94SStefano Zampini   i = 1;
3383e7931f94SStefano Zampini   if (color) i=0;
3384e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3385e7931f94SStefano Zampini 
3386e7931f94SStefano Zampini   /* get back IS */
3387e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3388e7931f94SStefano Zampini   PetscFunctionReturn(0);
3389e7931f94SStefano Zampini }
3390e7931f94SStefano Zampini 
3391e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3392e7931f94SStefano Zampini 
3393e7931f94SStefano Zampini #undef __FUNCT__
3394e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
339528143c3dSStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
3396e7931f94SStefano Zampini {
339770cf5478SStefano Zampini   Mat                    local_mat;
3398e7931f94SStefano Zampini   Mat_IS                 *matis;
3399e7931f94SStefano Zampini   IS                     is_sends_internal;
34009d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
340128143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
34029d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3403e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3404e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3405e7931f94SStefano Zampini   const PetscInt*        is_indices;
3406e7931f94SStefano Zampini   MatType                new_local_type;
3407e7931f94SStefano Zampini   /* buffers */
3408e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
340928143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
34109d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3411e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3412e7931f94SStefano Zampini   /* MPI */
341328143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
341428143c3dSStefano Zampini   PetscSubcomm           subcomm;
3415e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
341628143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
341728143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
341828143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
341928143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
342028143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3421e7931f94SStefano Zampini   PetscErrorCode         ierr;
3422e7931f94SStefano Zampini 
3423e7931f94SStefano Zampini   PetscFunctionBegin;
342428143c3dSStefano Zampini   /* TODO: add missing checks */
342528143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
342628143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
342728143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
342828143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3429e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
343028143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3431e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3432e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3433e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3434e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3435e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
343628143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
343770cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
343870cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
343928143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
344070cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
344170cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
344270cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
344370cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
344470cf5478SStefano Zampini   }
3445e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3446e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3447e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3448e7931f94SStefano Zampini   if (!is_sends) {
344928143c3dSStefano Zampini     PetscBool pcontig = PETSC_TRUE;
345028143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
345128143c3dSStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,pcontig,&is_sends_internal);CHKERRQ(ierr);
3452c8587f34SStefano Zampini   } else {
3453e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3454e7931f94SStefano Zampini     is_sends_internal = is_sends;
3455c8587f34SStefano Zampini   }
3456e7931f94SStefano Zampini 
3457e7931f94SStefano Zampini   /* get pointer of MATIS data */
3458e7931f94SStefano Zampini   matis = (Mat_IS*)mat->data;
3459e7931f94SStefano Zampini 
3460e7931f94SStefano Zampini   /* get comm */
3461a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3462e7931f94SStefano Zampini 
3463e7931f94SStefano Zampini   /* compute number of sends */
3464e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3465e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3466e7931f94SStefano Zampini 
3467e7931f94SStefano Zampini   /* compute number of receives */
3468e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3469785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3470e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3471e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3472e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3473e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3474e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3475e7931f94SStefano Zampini 
347628143c3dSStefano Zampini   /* restrict comm if requested */
347728143c3dSStefano Zampini   subcomm = 0;
347828143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
347928143c3dSStefano Zampini   if (restrict_comm) {
348028143c3dSStefano Zampini     PetscMPIInt color,rank,subcommsize;
348128143c3dSStefano Zampini     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
348228143c3dSStefano Zampini     color = 0;
348328143c3dSStefano Zampini     if (n_sends && !n_recvs) color = 1; /* sending only processes will not partecipate in new comm */
348428143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
348528143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
348628143c3dSStefano Zampini     /* check if reuse has been requested */
348728143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
348828143c3dSStefano Zampini       if (*mat_n) {
348928143c3dSStefano Zampini         PetscMPIInt subcommsize2;
349028143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
349128143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
349228143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
349328143c3dSStefano Zampini       } else {
349428143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
349528143c3dSStefano Zampini       }
349628143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
349728143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
349828143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
349928143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
350028143c3dSStefano Zampini       comm_n = subcomm->comm;
350128143c3dSStefano Zampini     }
350228143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
350328143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
350428143c3dSStefano Zampini   } else {
350528143c3dSStefano Zampini     comm_n = comm;
350628143c3dSStefano Zampini   }
350728143c3dSStefano Zampini 
3508e7931f94SStefano Zampini   /* prepare send/receive buffers */
3509785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
3510e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
3511785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
3512e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
351328143c3dSStefano Zampini   if (nis) {
3514854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
351528143c3dSStefano Zampini   }
3516e7931f94SStefano Zampini 
351728143c3dSStefano Zampini   /* Get data from local matrices */
3518e7931f94SStefano Zampini   if (!isdense) {
3519a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
3520e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
3521e7931f94SStefano Zampini     /*
3522e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
3523e7931f94SStefano Zampini        send_buffer_idxs should contain:
3524e7931f94SStefano Zampini        - MatType_PRIVATE type
3525e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
3526e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
3527e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
3528e7931f94SStefano Zampini     */
3529e7931f94SStefano Zampini   } else {
3530e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3531e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&i);CHKERRQ(ierr);
3532854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
3533e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
3534e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
3535e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3536e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
3537e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3538e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
3539e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
3540e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
3541e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
3542c8587f34SStefano Zampini     }
3543c8587f34SStefano Zampini   }
3544e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
354528143c3dSStefano Zampini   /* additional is (if any) */
354628143c3dSStefano Zampini   if (nis) {
354728143c3dSStefano Zampini     PetscMPIInt psum;
354828143c3dSStefano Zampini     PetscInt j;
354928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
355028143c3dSStefano Zampini       PetscInt plen;
355128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
355228143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
355328143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
355428143c3dSStefano Zampini     }
3555854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
355628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
355728143c3dSStefano Zampini       PetscInt plen;
355828143c3dSStefano Zampini       const PetscInt *is_array_idxs;
355928143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
356028143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
356128143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
356228143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
356328143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
356428143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
356528143c3dSStefano Zampini     }
356628143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
356728143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
356828143c3dSStefano Zampini     }
356928143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
357028143c3dSStefano Zampini   }
357128143c3dSStefano Zampini 
3572e7931f94SStefano Zampini   buf_size_idxs = 0;
3573e7931f94SStefano Zampini   buf_size_vals = 0;
357428143c3dSStefano Zampini   buf_size_idxs_is = 0;
3575e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3576e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
3577e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
357828143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
3579e7931f94SStefano Zampini   }
3580785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
3581785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
358295ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
3583e7931f94SStefano Zampini 
3584e7931f94SStefano Zampini   /* get new tags for clean communications */
3585e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
3586e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
358728143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
3588e7931f94SStefano Zampini 
3589e7931f94SStefano Zampini   /* allocate for requests */
3590785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
3591785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
359295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
3593785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
3594785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
359595ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
3596e7931f94SStefano Zampini 
3597e7931f94SStefano Zampini   /* communications */
3598e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
3599e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
360028143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
3601e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3602e7931f94SStefano Zampini     source_dest = onodes[i];
3603e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
3604e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
3605e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3606e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
360728143c3dSStefano Zampini     if (nis) {
360828143c3dSStefano 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);
360928143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
361028143c3dSStefano Zampini     }
3611e7931f94SStefano Zampini   }
3612e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
3613e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
3614e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
3615e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
361628143c3dSStefano Zampini     if (nis) {
361728143c3dSStefano 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);
361828143c3dSStefano Zampini     }
3619e7931f94SStefano Zampini   }
3620e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3621e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
3622e7931f94SStefano Zampini 
3623e7931f94SStefano Zampini   /* assemble new l2g map */
3624e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3625e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
36269d30be91SStefano Zampini   new_local_rows = 0;
3627e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
36289d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3629e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3630e7931f94SStefano Zampini   }
36319d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
3632e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
36339d30be91SStefano Zampini   new_local_rows = 0;
3634e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
36359d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
36369d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3637e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3638e7931f94SStefano Zampini   }
36399d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
36409d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
3641e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
3642e7931f94SStefano Zampini 
3643e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
3644e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
3645e7931f94SStefano 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) */
3646e7931f94SStefano Zampini   if (n_recvs) {
364728143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
3648e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
3649e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
3650e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
3651e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
3652e7931f94SStefano Zampini         break;
3653e7931f94SStefano Zampini       }
3654e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
3655e7931f94SStefano Zampini     }
3656e7931f94SStefano Zampini     switch (new_local_type_private) {
365728143c3dSStefano Zampini       case MATDENSE_PRIVATE:
365828143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
3659e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
3660e7931f94SStefano Zampini           bs = 1;
366128143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
366228143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
366328143c3dSStefano Zampini           bs = 1;
366428143c3dSStefano Zampini         }
3665e7931f94SStefano Zampini         break;
3666e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
3667e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
3668e7931f94SStefano Zampini         bs = 1;
3669e7931f94SStefano Zampini         break;
3670e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
3671e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
3672e7931f94SStefano Zampini         break;
3673e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
3674e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
3675e7931f94SStefano Zampini         break;
3676e7931f94SStefano Zampini       default:
36779d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
3678e7931f94SStefano Zampini         break;
3679e7931f94SStefano Zampini     }
368028143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
368128143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
368228143c3dSStefano Zampini     bs = 1;
3683e7931f94SStefano Zampini   }
3684e7931f94SStefano Zampini 
368570cf5478SStefano Zampini   /* create MATIS object if needed */
368670cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
3687e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
368828143c3dSStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,mat_n);CHKERRQ(ierr);
368970cf5478SStefano Zampini   } else {
369070cf5478SStefano Zampini     /* it also destroys the local matrices */
369170cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
369270cf5478SStefano Zampini   }
369370cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
3694e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
36959d30be91SStefano Zampini 
36969d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
36979d30be91SStefano Zampini 
36989d30be91SStefano Zampini   /* Global to local map of received indices */
36999d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
37009d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
37019d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
37029d30be91SStefano Zampini 
37039d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
37049d30be91SStefano Zampini   buf_size_idxs = 0;
37059d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
37069d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
37079d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
37089d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
37099d30be91SStefano Zampini   }
37109d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
37119d30be91SStefano Zampini 
37129d30be91SStefano Zampini   /* set preallocation */
37139d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
37149d30be91SStefano Zampini   if (!newisdense) {
37159d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
37169d30be91SStefano Zampini 
37179d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
37189d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
37199d30be91SStefano Zampini     if (n_recvs) {
37209d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
37219d30be91SStefano Zampini     }
37229d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
37239d30be91SStefano Zampini       PetscInt j;
37249d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
37259d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
37269d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
37279d30be91SStefano Zampini         }
37289d30be91SStefano Zampini       } else {
37299d30be91SStefano Zampini         /* TODO */
37309d30be91SStefano Zampini       }
37319d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
37329d30be91SStefano Zampini     }
37339d30be91SStefano Zampini     if (new_local_nnz) {
37349d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
37359d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
37369d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
37379d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
37389d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
37399d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
37409d30be91SStefano Zampini     } else {
37419d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
37429d30be91SStefano Zampini     }
37439d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
37449d30be91SStefano Zampini   } else {
37459d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
37469d30be91SStefano Zampini   }
3747e7931f94SStefano Zampini 
3748e7931f94SStefano Zampini   /* set values */
3749e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
37509d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
3751e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3752e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
3753e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
37549d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
3755e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3756e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3757e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
375828143c3dSStefano Zampini     } else {
375928143c3dSStefano Zampini       /* TODO */
3760e7931f94SStefano Zampini     }
3761e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3762e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
3763e7931f94SStefano Zampini   }
3764e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3765e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
376670cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
376770cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
37689d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
37699d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
3770e7931f94SStefano Zampini 
3771dfd14d43SStefano Zampini #if 0
377228143c3dSStefano Zampini   if (!restrict_comm) { /* check */
3773e7931f94SStefano Zampini     Vec       lvec,rvec;
3774e7931f94SStefano Zampini     PetscReal infty_error;
3775e7931f94SStefano Zampini 
37762a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
3777e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
3778e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
3779e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
378070cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
3781e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3782e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
3783e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
3784e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
3785e7931f94SStefano Zampini   }
378628143c3dSStefano Zampini #endif
3787e7931f94SStefano Zampini 
378828143c3dSStefano Zampini   /* assemble new additional is (if any) */
378928143c3dSStefano Zampini   if (nis) {
379028143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
379128143c3dSStefano Zampini 
379228143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3793854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
379428143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
379528143c3dSStefano Zampini     psum = 0;
379628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
379728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
379828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
379928143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
380028143c3dSStefano Zampini         psum += plen;
380128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
380228143c3dSStefano Zampini       }
380328143c3dSStefano Zampini     }
3804854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
3805854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
380628143c3dSStefano Zampini     for (i=1;i<nis;i++) {
380728143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
380828143c3dSStefano Zampini     }
380928143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
381028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
381128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
381228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
381328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
381428143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
381528143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
381628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
381728143c3dSStefano Zampini       }
381828143c3dSStefano Zampini     }
381928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
382028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
382128143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
382228143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
382328143c3dSStefano Zampini     }
382428143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
382528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
382628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
382728143c3dSStefano Zampini   }
3828e7931f94SStefano Zampini   /* free workspace */
382928143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
3830e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3831e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
3832e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3833e7931f94SStefano Zampini   if (isdense) {
3834e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3835e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3836e7931f94SStefano Zampini   } else {
3837e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
3838e7931f94SStefano Zampini   }
383928143c3dSStefano Zampini   if (nis) {
384028143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
384128143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
384228143c3dSStefano Zampini   }
3843e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
3844e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
384528143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
3846e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
3847e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
384828143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
3849e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
3850e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
3851e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
3852e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
3853e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
385428143c3dSStefano Zampini   if (nis) {
385528143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
385628143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
385728143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
385828143c3dSStefano Zampini   }
385928143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
386028143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
386128143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
386228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
386328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
386428143c3dSStefano Zampini     }
386528143c3dSStefano Zampini   }
3866e7931f94SStefano Zampini   PetscFunctionReturn(0);
3867e7931f94SStefano Zampini }
3868a57a6d2fSStefano Zampini 
386912edc857SStefano Zampini /* temporary hack into ksp private data structure */
387012edc857SStefano Zampini #include <petsc-private/kspimpl.h>
387112edc857SStefano Zampini 
3872c8587f34SStefano Zampini #undef __FUNCT__
3873c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
3874c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
3875c8587f34SStefano Zampini {
3876c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
3877c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
387820a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
38799881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
388020a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
38816e683305SStefano Zampini   IS                     coarse_is,*isarray;
38826e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
38836e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
3884f9eb5b7dSStefano Zampini   PC                     pc_temp;
3885c8587f34SStefano Zampini   PCType                 coarse_pc_type;
3886c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
3887f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
38884f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
38896e683305SStefano Zampini   Mat                    t_coarse_mat_is;
38906e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
38916e683305SStefano Zampini   PetscMPIInt            all_procs;
389274e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
389368457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
389422bc73bbSStefano Zampini   PetscScalar            *array;
38959881197aSStefano Zampini   PetscErrorCode         ierr;
3896fdc09c96SStefano Zampini 
3897c8587f34SStefano Zampini   PetscFunctionBegin;
3898c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
389968457ee5SStefano 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 */
390068457ee5SStefano Zampini     compute_vecs = PETSC_TRUE;
3901fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
3902fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
3903f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
3904f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
3905f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
3906fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
3907fa7f1dd8SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size) { /* ...but with different size, so reset it and set reuse flag to false */
3908727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3909fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
3910fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
3911fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
3912f4ddd8eeSStefano Zampini       }
3913fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
3914fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
3915f4ddd8eeSStefano Zampini     }
391670cf5478SStefano Zampini     /* reset any subassembling information */
391770cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
39186e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
39196e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
3920fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
3921f4ddd8eeSStefano Zampini   }
3922c8587f34SStefano Zampini 
39236e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
39242b510759SStefano Zampini   im_active = !!(pcis->n);
39252b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
39266e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
39276e683305SStefano Zampini   void_procs = all_procs-active_procs;
39286e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
392974e2c79eSStefano Zampini   redist = PETSC_FALSE;
393022bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
39316e683305SStefano Zampini     csin_ml = PETSC_TRUE;
39326e683305SStefano Zampini     ncoarse_ml = void_procs;
39336e683305SStefano Zampini     csin_ds = PETSC_TRUE;
39346e683305SStefano Zampini     ncoarse_ds = void_procs;
39356e683305SStefano Zampini   } else {
39366e683305SStefano Zampini     csin_ml = PETSC_FALSE;
39376e683305SStefano Zampini     ncoarse_ml = all_procs;
39386e683305SStefano Zampini     if (void_procs) {
39396e683305SStefano Zampini       csin_ds = PETSC_TRUE;
39406e683305SStefano Zampini       ncoarse_ds = void_procs;
39416e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
39426e683305SStefano Zampini     } else {
394374e2c79eSStefano Zampini       if (pcbddc->redistribute_coarse && pcbddc->redistribute_coarse < all_procs) {
394474e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
394574e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
394674e2c79eSStefano Zampini         redist = PETSC_TRUE;
394774e2c79eSStefano Zampini       } else {
39486e683305SStefano Zampini         csin_ds = PETSC_FALSE;
39496e683305SStefano Zampini         ncoarse_ds = all_procs;
39506e683305SStefano Zampini       }
39516e683305SStefano Zampini     }
395274e2c79eSStefano Zampini   }
39536e683305SStefano Zampini 
39546e683305SStefano Zampini   /*
39556e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
39566e683305SStefano Zampini     - we have not exceeded the number of levels requested
39576e683305SStefano Zampini     - we can actually subassemble the active processes
39586e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
39596e683305SStefano Zampini   */
39606e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
39616e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
39626e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
39636e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
39646e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
3965f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
39662b510759SStefano Zampini     } else {
3967f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
3968c8587f34SStefano Zampini     }
3969c8587f34SStefano Zampini   }
39706e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
39716e683305SStefano Zampini   if (multilevel_allowed) {
39726e683305SStefano Zampini     ncoarse = ncoarse_ml;
39736e683305SStefano Zampini     csin = csin_ml;
39746e683305SStefano Zampini   } else {
39756e683305SStefano Zampini     ncoarse = ncoarse_ds;
39766e683305SStefano Zampini     csin = csin_ds;
39776e683305SStefano Zampini   }
3978e7931f94SStefano Zampini 
3979abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
3980abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
3981abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
3982abbbba34SStefano Zampini 
3983abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
398422bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
398522bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
398622bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
398722bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
3988b9b85e73SStefano Zampini #if 0
3989b9b85e73SStefano Zampini   {
3990b9b85e73SStefano Zampini     PetscViewer viewer;
3991b9b85e73SStefano Zampini     char filename[256];
3992b9b85e73SStefano Zampini     sprintf(filename,"local_coarse_mat%d.m",PetscGlobalRank);
3993b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3994b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3995b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
3996b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3997b9b85e73SStefano Zampini   }
3998b9b85e73SStefano Zampini #endif
39996e683305SStefano 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);
40006e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
40016e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
40026e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4003abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4004abbbba34SStefano Zampini 
40056e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
40066e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
40076e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
40086e683305SStefano Zampini     const PetscInt         *idxs;
40096e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
40106e683305SStefano Zampini 
40116e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
40120be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
40136e683305SStefano Zampini     /* allocate space for temporary storage */
4014854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4015854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
40166e683305SStefano Zampini     /* allocate for IS array */
40176e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
40186e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
40196e683305SStefano Zampini     nis = nisdofs + nisneu;
4020854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
40216e683305SStefano Zampini     /* dofs splitting */
40226e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
40236e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
40246e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
40256e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
40266e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
40276e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
40286e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
40296e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
40306e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
40316e683305SStefano Zampini     }
40326e683305SStefano Zampini     /* neumann boundaries */
40336e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
40346e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
40356e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
40366e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
40376e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
40386e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
40396e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
40406e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
40416e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
40426e683305SStefano Zampini     }
40436e683305SStefano Zampini     /* free memory */
40446e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
40456e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
40466e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
40476e683305SStefano Zampini   } else {
40486e683305SStefano Zampini     nis = 0;
40496e683305SStefano Zampini     nisdofs = 0;
40506e683305SStefano Zampini     nisneu = 0;
40516e683305SStefano Zampini     isarray = NULL;
40526e683305SStefano Zampini   }
40536e683305SStefano Zampini   /* destroy no longer needed map */
40546e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
40556e683305SStefano Zampini 
40566e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
40576e683305SStefano Zampini   coarse_mat_is = NULL;
40586e683305SStefano Zampini   if (csin) {
40596e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
406074e2c79eSStefano Zampini       if (redist) {
406174e2c79eSStefano Zampini         PetscMPIInt rank;
406274e2c79eSStefano Zampini         PetscInt spc,n_spc_p1,dest[1];
406374e2c79eSStefano Zampini 
406474e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
406574e2c79eSStefano Zampini         spc = all_procs/pcbddc->redistribute_coarse;
406674e2c79eSStefano Zampini         n_spc_p1 = all_procs%pcbddc->redistribute_coarse;
406774e2c79eSStefano Zampini         if (rank > n_spc_p1*(spc+1)-1) {
406874e2c79eSStefano Zampini           dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
406974e2c79eSStefano Zampini         } else {
407074e2c79eSStefano Zampini           dest[0] = rank/(spc+1);
407174e2c79eSStefano Zampini         }
407274e2c79eSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),1,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
407374e2c79eSStefano Zampini       } else {
40746e683305SStefano Zampini         PetscInt j,tissize,*nisindices;
40756e683305SStefano Zampini         PetscInt *coarse_candidates;
40766e683305SStefano Zampini         const PetscInt* tisindices;
40776e683305SStefano Zampini         /* get coarse candidates' ranks in pc communicator */
4078854ce69bSBarry Smith         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
40796e683305SStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
40806e683305SStefano Zampini         for (i=0,j=0;i<all_procs;i++) {
40816e683305SStefano Zampini           if (!coarse_candidates[i]) {
40826e683305SStefano Zampini             coarse_candidates[j]=i;
40836e683305SStefano Zampini             j++;
40846e683305SStefano Zampini           }
40856e683305SStefano Zampini         }
40866e683305SStefano Zampini         if (j < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",j,ncoarse);
40876e683305SStefano Zampini         /* get a suitable subassembling pattern */
40886e683305SStefano Zampini         if (csin_type_simple) {
40896e683305SStefano Zampini           PetscMPIInt rank;
40906e683305SStefano Zampini           PetscInt    issize,isidx;
40916e683305SStefano Zampini           ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
40926e683305SStefano Zampini           if (im_active) {
40936e683305SStefano Zampini             issize = 1;
40946e683305SStefano Zampini             isidx = (PetscInt)rank;
40956e683305SStefano Zampini           } else {
40966e683305SStefano Zampini             issize = 0;
40976e683305SStefano Zampini             isidx = -1;
40986e683305SStefano Zampini           }
40996e683305SStefano Zampini           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
41006e683305SStefano Zampini         } else {
41016e683305SStefano Zampini           ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,PETSC_TRUE,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
41026e683305SStefano Zampini         }
41036e683305SStefano Zampini         if (pcbddc->dbg_flag) {
41046e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
41056e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
41066e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
41076e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
41086e683305SStefano Zampini           for (i=0;i<j;i++) {
41096e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
41106e683305SStefano Zampini           }
41116e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
41126e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
41136e683305SStefano Zampini         }
41146e683305SStefano Zampini         /* shift the pattern on coarse candidates */
41156e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
41166e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
4117854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
41186e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
41196e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
41206e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
41216e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
41226e683305SStefano Zampini       }
412374e2c79eSStefano Zampini     }
41246e683305SStefano Zampini     if (pcbddc->dbg_flag) {
41256e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
41266e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
41276e683305SStefano Zampini       ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
41286e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
41296e683305SStefano Zampini     }
41306e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
41316e683305SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
41326e683305SStefano Zampini   } else {
41336e683305SStefano Zampini     if (pcbddc->dbg_flag) {
41346e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
41356e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
41366e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
41376e683305SStefano Zampini     }
41386e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
41396e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
41406e683305SStefano Zampini   }
41416e683305SStefano Zampini 
41426e683305SStefano Zampini   /* create local to global scatters for coarse problem */
414368457ee5SStefano Zampini   if (compute_vecs) {
41446e683305SStefano Zampini     PetscInt lrows;
41456e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
41466e683305SStefano Zampini     if (coarse_mat_is) {
41476e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
41486e683305SStefano Zampini     } else {
41496e683305SStefano Zampini       lrows = 0;
41506e683305SStefano Zampini     }
41516e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
41526e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
41536e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
41546e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
41556e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
41566e683305SStefano Zampini   }
41576e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
41586e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
4159c8587f34SStefano Zampini 
4160f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
4161f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
4162f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
4163f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
4164f9eb5b7dSStefano Zampini   } else {
4165f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
4166f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
4167c8587f34SStefano Zampini   }
4168c8587f34SStefano Zampini 
41696e683305SStefano Zampini   /* print some info if requested */
41706e683305SStefano Zampini   if (pcbddc->dbg_flag) {
41716e683305SStefano Zampini     if (!multilevel_allowed) {
41726e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
41736e683305SStefano Zampini       if (multilevel_requested) {
41746e683305SStefano 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);
41756e683305SStefano Zampini       } else if (pcbddc->max_levels) {
41766e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
41776e683305SStefano Zampini       }
41786e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
41796e683305SStefano Zampini     }
41806e683305SStefano Zampini   }
41816e683305SStefano Zampini 
4182f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
41836e683305SStefano Zampini   if (coarse_mat_is) {
41846e683305SStefano Zampini     MatReuse coarse_mat_reuse;
41856a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
41866e683305SStefano Zampini     if (pcbddc->dbg_flag) {
41876e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
41886e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
41896e683305SStefano Zampini     }
4190f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
4191312be037SStefano Zampini       char prefix[256],str_level[16];
4192e604994aSStefano Zampini       size_t len;
41936e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
4194c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
4195f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
41965f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
4197c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
41986e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
4199c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4200c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4201e604994aSStefano Zampini       /* prefix */
4202e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
4203e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4204e604994aSStefano Zampini       if (!pcbddc->current_level) {
4205e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4206e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
4207c8587f34SStefano Zampini       } else {
4208e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4209312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4210312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
421134d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4212312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4213e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
4214e604994aSStefano Zampini       }
4215e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
4216f9eb5b7dSStefano Zampini       /* allow user customization */
4217f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
42187e0def11SStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4219312be037SStefano Zampini     }
4220f9eb5b7dSStefano Zampini 
4221f9eb5b7dSStefano Zampini     /* get some info after set from options */
4222f9eb5b7dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4223f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
4224f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
42254f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
42266e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
4227f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4228f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
4229f9eb5b7dSStefano Zampini     }
42304f3a063dSStefano Zampini     if (isredundant) {
42314f3a063dSStefano Zampini       KSP inner_ksp;
42324f3a063dSStefano Zampini       PC inner_pc;
42334f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
42344f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
42354f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
42364f3a063dSStefano Zampini     }
4237f9eb5b7dSStefano Zampini 
42386e683305SStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
4239f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
4240f9eb5b7dSStefano Zampini     ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
4241f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
42426e683305SStefano Zampini     if (nisdofs) {
42436e683305SStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
42446e683305SStefano Zampini       for (i=0;i<nisdofs;i++) {
42456e683305SStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
42461035eff8SStefano Zampini       }
42471035eff8SStefano Zampini     }
42486e683305SStefano Zampini     if (nisneu) {
42496e683305SStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
42506e683305SStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
42511035eff8SStefano Zampini     }
4252fdc09c96SStefano Zampini 
4253f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
4254fa7f1dd8SStefano Zampini     if (coarse_reuse) {
425581d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
4256fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
42576e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
4258fa7f1dd8SStefano Zampini     } else {
42596e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
4260fa7f1dd8SStefano Zampini     }
4261c8587f34SStefano Zampini     if (isbddc || isnn) {
426222bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
426370cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
426428143c3dSStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,PETSC_TRUE,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
426522b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
42666e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
42676e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
42686e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
42696e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
427022b6e8a2SStefano Zampini           }
427170cf5478SStefano Zampini         }
42726e683305SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
427370cf5478SStefano Zampini       } else {
427422bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
427522bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
427622bc73bbSStefano Zampini       }
427722bc73bbSStefano Zampini     } else {
42782e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
4279c8587f34SStefano Zampini     }
4280c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
4281c8587f34SStefano Zampini 
4282c8587f34SStefano Zampini     /* propagate symmetry info to coarse matrix */
4283b9d89cd5SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
42845a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
4285c8587f34SStefano Zampini 
42866e683305SStefano Zampini     /* set operators */
42875f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
42886e683305SStefano Zampini     if (pcbddc->dbg_flag) {
42896e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
42906e683305SStefano Zampini     }
42916e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
42926e683305SStefano Zampini     coarse_mat = 0;
42936e683305SStefano Zampini   }
42946e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
4295b9b85e73SStefano Zampini #if 0
4296b9b85e73SStefano Zampini   {
4297b9b85e73SStefano Zampini     PetscViewer viewer;
4298b9b85e73SStefano Zampini     char filename[256];
4299b9b85e73SStefano Zampini     sprintf(filename,"coarse_mat.m");
4300b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,filename,&viewer);CHKERRQ(ierr);
4301b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4302b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4303b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4304b9b85e73SStefano Zampini   }
4305b9b85e73SStefano Zampini #endif
4306c8587f34SStefano Zampini 
4307c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4308c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4309c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
431098a51de6SStefano Zampini   }
431198a51de6SStefano Zampini 
431298a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
431398a51de6SStefano Zampini     Vec crhs,csol;
431498a51de6SStefano Zampini     PetscBool ispreonly;
431598a51de6SStefano Zampini     if (CoarseNullSpace) {
4316c8587f34SStefano Zampini       if (isbddc) {
4317c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4318c8587f34SStefano Zampini       } else {
4319c8587f34SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
4320c8587f34SStefano Zampini       }
4321c8587f34SStefano Zampini     }
4322f9eb5b7dSStefano Zampini     /* setup coarse ksp */
4323f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4324f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4325f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
43266e683305SStefano Zampini     /* hack */
4327f347579bSStefano Zampini     if (!csol) {
43282a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4329f9eb5b7dSStefano Zampini     }
4330f347579bSStefano Zampini     if (!crhs) {
43312a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4332f347579bSStefano Zampini     }
4333cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4334cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
43356e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4336c8587f34SStefano Zampini       KSP       check_ksp;
43372b510759SStefano Zampini       KSPType   check_ksp_type;
4338c8587f34SStefano Zampini       PC        check_pc;
43396e683305SStefano Zampini       Vec       check_vec,coarse_vec;
43406a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
43412b510759SStefano Zampini       PetscInt  its;
43426e683305SStefano Zampini       PetscBool compute_eigs;
43436e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
43446e683305SStefano Zampini       PetscInt  neigs;
43458e185a42SStefano Zampini       const char *prefix;
4346c8587f34SStefano Zampini 
43472b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
43486e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
434923ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4350f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
43512b510759SStefano Zampini       if (ispreonly) {
43522b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
43536e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
43542b510759SStefano Zampini       } else {
4355cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
43566e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4357c8587f34SStefano Zampini       }
4358c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
43596e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
43606e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
43616e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4362a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4363a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4364a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4365a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4366c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4367c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4368c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4369c8587f34SStefano Zampini       /* create random vec */
43706e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
43716e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
4372c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
4373c8587f34SStefano Zampini       if (CoarseNullSpace) {
4374c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
4375c8587f34SStefano Zampini       }
43766e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
4377c8587f34SStefano Zampini       /* solve coarse problem */
43786e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
4379c8587f34SStefano Zampini       if (CoarseNullSpace) {
43806e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
4381c8587f34SStefano Zampini       }
4382cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
43836e683305SStefano Zampini       if (compute_eigs) {
4384854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4385854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
43866e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
43876e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
43886e683305SStefano Zampini         lambda_min = eigs_r[0];
43896e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
43906e683305SStefano Zampini           if (lambda_max>lambda_min) {
4391cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4392cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4393cbcc2c2aSStefano Zampini           }
4394c8587f34SStefano Zampini         }
4395c8587f34SStefano Zampini       }
4396cbcc2c2aSStefano Zampini 
4397c8587f34SStefano Zampini       /* check coarse problem residual error */
43986e683305SStefano Zampini       if (pcbddc->dbg_flag) {
43996e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
44006e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
44016e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4402c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
44036e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
44046e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4405c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
44066e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (%d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
44076e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
44086e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
44096e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
44106e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
44116e683305SStefano Zampini         if (compute_eigs) {
44126e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4413deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4414c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
44156e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
44166e683305SStefano 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);
44176e683305SStefano Zampini           for (i=0;i<neigs;i++) {
44186e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4419c8587f34SStefano Zampini           }
44206e683305SStefano Zampini         }
44216e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
44226e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
44236e683305SStefano Zampini       }
4424c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
44256e683305SStefano Zampini       if (compute_eigs) {
44266e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
44276e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4428c8587f34SStefano Zampini       }
44296e683305SStefano Zampini     }
44306e683305SStefano Zampini   }
4431cbcc2c2aSStefano Zampini   /* print additional info */
4432cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
44336e683305SStefano Zampini     /* waits until all processes reaches this point */
44346e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4435cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4436cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4437cbcc2c2aSStefano Zampini   }
4438cbcc2c2aSStefano Zampini 
44392b510759SStefano Zampini   /* free memory */
4440c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4441fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4442c8587f34SStefano Zampini   PetscFunctionReturn(0);
4443c8587f34SStefano Zampini }
4444674ae819SStefano Zampini 
4445f34684f1SStefano Zampini #undef __FUNCT__
4446f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4447f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4448f34684f1SStefano Zampini {
4449f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4450f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
4451f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
4452727cdba6SStefano Zampini   PetscInt       i,coarse_size;
4453727cdba6SStefano Zampini   PetscInt       *local_primal_indices;
4454f34684f1SStefano Zampini   PetscErrorCode ierr;
4455f34684f1SStefano Zampini 
4456f34684f1SStefano Zampini   PetscFunctionBegin;
4457f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
445889c96988SStefano Zampini   if (!pcbddc->primal_indices_local_idxs && pcbddc->local_primal_size) {
445989c96988SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Local primal indices have not been created");
4460727cdba6SStefano Zampini   }
4461727cdba6SStefano 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);
4462f34684f1SStefano Zampini 
4463f34684f1SStefano Zampini   /* check numbering */
4464f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
4465f34684f1SStefano Zampini     PetscScalar coarsesum,*array;
4466b9b85e73SStefano Zampini     PetscBool set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
4467f34684f1SStefano Zampini 
4468f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4469f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4470f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
44710fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
4472f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4473f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4474727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4475f34684f1SStefano Zampini     }
4476f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4477f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4478f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4479f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4480f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4481f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4482f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4483f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4484f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4485f34684f1SStefano Zampini       if (array[i] == 1.0) {
4486b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
4487f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a single process!\n",PetscGlobalRank,i);CHKERRQ(ierr);
4488f34684f1SStefano Zampini       }
4489f34684f1SStefano Zampini     }
4490b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4491f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4492f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4493f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
4494f34684f1SStefano Zampini     }
4495f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4496f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4497f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4498f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4499f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
4500f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
4501b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
4502f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
4503f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4504f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4505f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
4506727cdba6SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i]);
4507f34684f1SStefano Zampini       }
4508f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4509f34684f1SStefano Zampini     }
4510f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4511b9b85e73SStefano Zampini     if (set_error_reduced) {
4512b9b85e73SStefano Zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
4513b9b85e73SStefano Zampini     }
4514f34684f1SStefano Zampini   }
4515f34684f1SStefano Zampini   /* get back data */
4516f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
4517f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
4518674ae819SStefano Zampini   PetscFunctionReturn(0);
4519674ae819SStefano Zampini }
4520674ae819SStefano Zampini 
4521e456f2a8SStefano Zampini #undef __FUNCT__
4522e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
4523a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
4524e456f2a8SStefano Zampini {
4525e456f2a8SStefano Zampini   IS             localis_t;
4526a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
4527e456f2a8SStefano Zampini   PetscScalar    *vals;
4528e456f2a8SStefano Zampini   PetscErrorCode ierr;
4529e456f2a8SStefano Zampini 
4530e456f2a8SStefano Zampini   PetscFunctionBegin;
4531a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
4532e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
4533854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
4534e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
4535e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4536a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
4537a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
45381035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
4539a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
45401035eff8SStefano Zampini   }
4541a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
4542e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4543e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
4544a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
4545a7dc3881SStefano Zampini   /* now compute set in local ordering */
4546a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4547a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4548a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4549a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
4550a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4551ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4552e456f2a8SStefano Zampini       lsize++;
4553e456f2a8SStefano Zampini     }
4554e456f2a8SStefano Zampini   }
4555854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
4556a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4557ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4558e456f2a8SStefano Zampini       idxs[lsize++] = i;
4559e456f2a8SStefano Zampini     }
4560e456f2a8SStefano Zampini   }
4561a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4562a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
4563e456f2a8SStefano Zampini   *localis = localis_t;
4564e456f2a8SStefano Zampini   PetscFunctionReturn(0);
4565e456f2a8SStefano Zampini }
4566906d46d4SStefano Zampini 
4567906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
4568906d46d4SStefano Zampini #undef __FUNCT__
4569906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
4570906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
4571906d46d4SStefano Zampini {
4572906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4573906d46d4SStefano Zampini   PetscErrorCode   ierr;
4574906d46d4SStefano Zampini 
4575906d46d4SStefano Zampini   PetscFunctionBegin;
4576906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4577906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4578906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4579906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4580906d46d4SStefano Zampini   PetscFunctionReturn(0);
4581906d46d4SStefano Zampini }
4582906d46d4SStefano Zampini 
4583906d46d4SStefano Zampini #undef __FUNCT__
4584906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
4585906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
4586906d46d4SStefano Zampini {
4587906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4588906d46d4SStefano Zampini   PetscErrorCode   ierr;
4589906d46d4SStefano Zampini 
4590906d46d4SStefano Zampini   PetscFunctionBegin;
4591906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4592906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4593906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4594906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4595906d46d4SStefano Zampini   PetscFunctionReturn(0);
4596906d46d4SStefano Zampini }
4597b96c3477SStefano Zampini 
4598b96c3477SStefano Zampini #undef __FUNCT__
4599b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
460008122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
4601b96c3477SStefano Zampini {
4602b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4603b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4604b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
4605b96c3477SStefano Zampini   PetscBool           free_used_adj;
4606b96c3477SStefano Zampini   PetscErrorCode      ierr;
4607b96c3477SStefano Zampini 
4608b96c3477SStefano Zampini   PetscFunctionBegin;
4609b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
4610b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
461108122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
4612b96c3477SStefano Zampini     used_xadj = NULL;
4613b96c3477SStefano Zampini     used_adjncy = NULL;
4614b96c3477SStefano Zampini   } else {
461508122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
461608122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
461708122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
461808122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
4619b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
4620b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
4621b96c3477SStefano Zampini     } else {
4622b96c3477SStefano Zampini       Mat            mat_adj;
4623b96c3477SStefano Zampini       PetscBool      flg_row=PETSC_TRUE;
4624b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
4625b96c3477SStefano Zampini       PetscInt       nvtxs;
4626b96c3477SStefano Zampini 
4627b96c3477SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
4628b96c3477SStefano Zampini       ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4629b96c3477SStefano Zampini       if (!flg_row) {
4630b96c3477SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
4631b96c3477SStefano Zampini       }
4632b96c3477SStefano Zampini       ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
4633b96c3477SStefano Zampini       ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
4634b96c3477SStefano Zampini       ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
4635b96c3477SStefano Zampini       ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4636b96c3477SStefano Zampini       if (!flg_row) {
4637b96c3477SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
4638b96c3477SStefano Zampini       }
4639b96c3477SStefano Zampini       ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
4640b96c3477SStefano Zampini       free_used_adj = PETSC_TRUE;
4641b96c3477SStefano Zampini     }
4642b96c3477SStefano Zampini   }
464308122e43SStefano 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);
4644b96c3477SStefano Zampini 
4645b96c3477SStefano Zampini   /* free adjacency */
4646b96c3477SStefano Zampini   if (free_used_adj) {
4647b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
4648b96c3477SStefano Zampini   }
4649b96c3477SStefano Zampini   PetscFunctionReturn(0);
4650b96c3477SStefano Zampini }
4651b96c3477SStefano Zampini 
4652b96c3477SStefano Zampini #undef __FUNCT__
4653b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
465408122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
4655b96c3477SStefano Zampini {
4656b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
4657b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4658b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4659b96c3477SStefano Zampini   PCBDDCGraph         graph;
4660b96c3477SStefano Zampini   Mat                 S_j;
4661b96c3477SStefano Zampini   PetscErrorCode      ierr;
4662b96c3477SStefano Zampini 
4663b96c3477SStefano Zampini   PetscFunctionBegin;
4664b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
466508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
4666b96c3477SStefano Zampini     IS verticesIS;
4667b96c3477SStefano Zampini 
4668b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
4669b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
4670b96c3477SStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap);CHKERRQ(ierr);
4671b96c3477SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticesIS);CHKERRQ(ierr);
4672b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4673b96c3477SStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
4674b96c3477SStefano Zampini /*
4675b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
4676b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4677b96c3477SStefano Zampini     }
4678b96c3477SStefano Zampini */
4679b96c3477SStefano Zampini   } else {
4680b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
4681b96c3477SStefano Zampini   }
4682b96c3477SStefano Zampini 
4683b96c3477SStefano Zampini   /* Create Schur complement matrix */
4684b96c3477SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
4685b96c3477SStefano Zampini   ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
4686b96c3477SStefano Zampini 
4687b96c3477SStefano Zampini   /* sub_schurs init */
468808122e43SStefano 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);
4689b96c3477SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
4690b96c3477SStefano Zampini   /* free graph struct */
469108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
4692b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
4693b96c3477SStefano Zampini   }
4694b96c3477SStefano Zampini   PetscFunctionReturn(0);
4695b96c3477SStefano Zampini }
4696