xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision a58a30b4bf9d00545e20033ff3f2527e68041eaf)
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;
82*a58a30b4SStefano Zampini       eigs = NULL;
83*a58a30b4SStefano Zampini       eigv = NULL;
84*a58a30b4SStefano Zampini       B_iwork = NULL;
85*a58a30b4SStefano Zampini       B_ifail = NULL;
8608122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
8708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
8808122e43SStefano 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));
8908122e43SStefano Zampini #else
9008122e43SStefano 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));
9108122e43SStefano Zampini #endif
9208122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
9308122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
9408122e43SStefano Zampini     } else {
9508122e43SStefano Zampini         /* TODO */
9608122e43SStefano Zampini     }
9708122e43SStefano Zampini   } else {
9808122e43SStefano Zampini     lwork = 0;
9908122e43SStefano Zampini   }
10008122e43SStefano Zampini 
10108122e43SStefano Zampini   nv = 0;
10208122e43SStefano Zampini   if (sub_schurs->is_Ej_com) { /* complement of subsets, each entry is a vertex */
10308122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_Ej_com,&nv);CHKERRQ(ierr);
10408122e43SStefano Zampini   }
10508122e43SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)lwork,&B_lwork);CHKERRQ(ierr);
10608122e43SStefano Zampini   ierr = PetscMalloc7(mss*mss,&S,mss*mss,&St,mss*mss,&eigv,mss,&eigs,
10708122e43SStefano Zampini                       B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
10808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
10908122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
11008122e43SStefano Zampini #endif
11108122e43SStefano Zampini   ierr = PetscMalloc2(mss*mss,&Smult,mss*mss,&Seigv);CHKERRQ(ierr);
11208122e43SStefano Zampini   ierr = PetscMalloc4(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
11308122e43SStefano Zampini                       nv+cum2+1,&pcbddc->adaptive_constraints_ptrs,
11408122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
11508122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
11608122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
11708122e43SStefano Zampini 
11808122e43SStefano Zampini   maxneigs = 0;
11908122e43SStefano Zampini   cum = cum2 = cumarray = 0;
12008122e43SStefano Zampini   if (sub_schurs->is_Ej_com) {
12108122e43SStefano Zampini     const PetscInt *idxs;
12208122e43SStefano Zampini 
12308122e43SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_Ej_com,&idxs);CHKERRQ(ierr);
12408122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
12508122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
12608122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
12708122e43SStefano Zampini       pcbddc->adaptive_constraints_ptrs[cum] = cum;
12808122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
12908122e43SStefano Zampini     }
13008122e43SStefano Zampini     cum2 = cum;
13108122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_Ej_com,&idxs);CHKERRQ(ierr);
13208122e43SStefano Zampini   }
13308122e43SStefano Zampini 
13408122e43SStefano Zampini   if (mss) { /* multilevel */
13508122e43SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
13608122e43SStefano Zampini       ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
13708122e43SStefano Zampini     } else {
13808122e43SStefano Zampini       ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all,&Sarray);CHKERRQ(ierr);
13908122e43SStefano Zampini     }
14008122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
14108122e43SStefano Zampini   }
14208122e43SStefano Zampini 
14308122e43SStefano Zampini   cumsubs = 0;
14408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
14508122e43SStefano Zampini     PetscInt j,subset_size;
14608122e43SStefano Zampini 
14708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
14808122e43SStefano Zampini     if (PetscBTLookup(sub_schurs->computed_Stilda_subs,i)) {
14908122e43SStefano Zampini       const PetscInt *idxs;
15008122e43SStefano Zampini       PetscScalar    one = 1.0,zero=0.0;
15108122e43SStefano Zampini       PetscBLASInt   B_N;
15208122e43SStefano Zampini 
15308122e43SStefano Zampini       /* S should be copied since we need it for deluxe scaling */
15408122e43SStefano Zampini       if (symmetric) {
15508122e43SStefano Zampini         PetscInt j;
15608122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
15708122e43SStefano Zampini           ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
15808122e43SStefano Zampini         }
15908122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
16008122e43SStefano Zampini           ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
16108122e43SStefano Zampini         }
16208122e43SStefano Zampini       } else {
16308122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
16408122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
16508122e43SStefano Zampini       }
16608122e43SStefano Zampini       /* is always this the right matrix? */
16708122e43SStefano Zampini       ierr = PetscMemcpy(Smult,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
16808122e43SStefano Zampini 
16908122e43SStefano Zampini       /* we could reuse space already allocated when building sum_S_Ej_tilda_all */
17008122e43SStefano Zampini       /* St = Starray+cumarray; */
17108122e43SStefano Zampini 
17208122e43SStefano Zampini       if (symmetric) {
17308122e43SStefano Zampini         PetscBLASInt B_itype = 1;
17408122e43SStefano Zampini         PetscBLASInt B_IL = 1, B_IU;
17508122e43SStefano Zampini         PetscScalar  eps = -1.0; /* dlamch? */
17608122e43SStefano Zampini 
17708122e43SStefano Zampini         /* ask for eigenvalues lower than thresh */
17808122e43SStefano Zampini         PetscPrintf(PETSC_COMM_SELF,"[%d] Computing for sub %d/%d.\n",PetscGlobalRank,i,sub_schurs->n_subs);
17908122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
18008122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
18108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
18208122e43SStefano 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));
18308122e43SStefano Zampini #else
18408122e43SStefano 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));
18508122e43SStefano Zampini #endif
18608122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
18708122e43SStefano Zampini         if (B_ierr) {
18808122e43SStefano Zampini           if (B_ierr < 0 ) {
18908122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
19008122e43SStefano Zampini           } else if (B_ierr <= B_N) {
19108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
19208122e43SStefano Zampini           } else {
19308122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d principal minor not posdef",(int)B_ierr-B_N-1);
19408122e43SStefano Zampini           }
19508122e43SStefano Zampini         }
19608122e43SStefano Zampini 
19708122e43SStefano Zampini         if (B_neigs > nmax) {
19808122e43SStefano Zampini           PetscPrintf(PETSC_COMM_SELF,"[%d]   found %d eigs, more than required %d.\n",PetscGlobalRank,B_neigs,nmax);
19908122e43SStefano Zampini           B_neigs = nmax;
20008122e43SStefano Zampini         }
20108122e43SStefano Zampini 
20208122e43SStefano Zampini         if (B_neigs < nmin) {
20308122e43SStefano Zampini           PetscBLASInt B_neigs2;
20408122e43SStefano Zampini 
20508122e43SStefano Zampini           B_IL = B_neigs + 1;
20608122e43SStefano Zampini           ierr = PetscBLASIntCast(nmin,&B_IU);CHKERRQ(ierr);
20708122e43SStefano 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);
20808122e43SStefano Zampini           if (symmetric) {
20908122e43SStefano Zampini             PetscInt j;
21008122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
21108122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
21208122e43SStefano Zampini             }
21308122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
21408122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
21508122e43SStefano Zampini             }
21608122e43SStefano Zampini           } else {
21708122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
21808122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
21908122e43SStefano Zampini           }
22008122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
22108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
22208122e43SStefano 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));
22308122e43SStefano Zampini #else
22408122e43SStefano 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));
22508122e43SStefano Zampini #endif
22608122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
22708122e43SStefano Zampini           B_neigs += B_neigs2;
22808122e43SStefano Zampini         }
22908122e43SStefano Zampini         if (B_ierr) {
23008122e43SStefano Zampini           if (B_ierr < 0 ) {
23108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
23208122e43SStefano Zampini           } else if (B_ierr <= B_N) {
23308122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
23408122e43SStefano Zampini           } else {
23508122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d principal minor not posdef",(int)B_ierr-B_N-1);
23608122e43SStefano Zampini           }
23708122e43SStefano Zampini         }
23808122e43SStefano Zampini         PetscPrintf(PETSC_COMM_SELF,"[%d]   -> Got %d eigs\n",PetscGlobalRank,B_neigs);
23908122e43SStefano Zampini         for (j=0;j<B_neigs;j++) {
24008122e43SStefano Zampini           if (eigs[j] == 0.0) {
24108122e43SStefano Zampini             PetscPrintf(PETSC_COMM_SELF,"[%d]     Inf\n",PetscGlobalRank);
24208122e43SStefano Zampini           } else {
24308122e43SStefano Zampini             PetscPrintf(PETSC_COMM_SELF,"[%d]     %1.6e\n",PetscGlobalRank,1.0/eigs[j]);
24408122e43SStefano Zampini           }
24508122e43SStefano Zampini         }
24608122e43SStefano Zampini       } else {
24708122e43SStefano Zampini           /* TODO */
24808122e43SStefano Zampini       }
24908122e43SStefano Zampini       maxneigs = PetscMax(B_neigs,maxneigs);
25008122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cumsubs+nv] = B_neigs;
25108122e43SStefano Zampini       cumsubs++;
25208122e43SStefano Zampini 
25308122e43SStefano Zampini       ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
25408122e43SStefano Zampini       PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&B_N,&B_neigs,&B_N,&one,Smult,&B_N,eigv,&B_N,&zero,Seigv,&B_N));
25508122e43SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_data+cum2,Seigv,B_neigs*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
25608122e43SStefano Zampini       ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
25708122e43SStefano Zampini       for (j=0;j<B_neigs;j++) {
25808122e43SStefano Zampini #if 0
25908122e43SStefano Zampini         {
26008122e43SStefano Zampini           PetscBLASInt Blas_N,Blas_one = 1.0;
26108122e43SStefano Zampini           PetscScalar norm;
26208122e43SStefano Zampini           ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
26308122e43SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+cum2,&Blas_one,pcbddc->adaptive_constraints_data+cum2,&Blas_one));
26408122e43SStefano Zampini           if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
26508122e43SStefano Zampini             norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
26608122e43SStefano Zampini           } else {
26708122e43SStefano Zampini             norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
26808122e43SStefano Zampini           }
26908122e43SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+cum2,&Blas_one));
270b1b3d7a2SStefano Zampini         }
271b1b3d7a2SStefano Zampini #endif
27208122e43SStefano Zampini         ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+cum2,idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
27308122e43SStefano Zampini         pcbddc->adaptive_constraints_ptrs[cum++] = cum2;
27408122e43SStefano Zampini         cum2 += subset_size;
27508122e43SStefano Zampini       }
27608122e43SStefano Zampini       ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
27708122e43SStefano Zampini     }
27808122e43SStefano Zampini     /* shift for next computation */
27908122e43SStefano Zampini     cumarray += subset_size*subset_size;
28008122e43SStefano Zampini   }
28108122e43SStefano Zampini   pcbddc->adaptive_constraints_ptrs[cum] = cum2;
28208122e43SStefano Zampini   ierr = PetscFree2(Smult,Seigv);CHKERRQ(ierr);
28308122e43SStefano Zampini 
28408122e43SStefano Zampini   if (mss) {
28508122e43SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
28608122e43SStefano Zampini       ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
28708122e43SStefano Zampini     } else {
28808122e43SStefano Zampini       ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_all,&Sarray);CHKERRQ(ierr);
28908122e43SStefano Zampini     }
29008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
29108122e43SStefano Zampini   }
29208122e43SStefano Zampini   ierr = PetscFree7(S,St,eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
29308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
29408122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
29508122e43SStefano Zampini #endif
29608122e43SStefano Zampini   if (pcbddc->dbg_flag) {
29708122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
29808122e43SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
29908122e43SStefano Zampini   }
30008122e43SStefano Zampini   PetscFunctionReturn(0);
30108122e43SStefano Zampini }
302b1b3d7a2SStefano Zampini 
303674ae819SStefano Zampini #undef __FUNCT__
304c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
305c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
306c8587f34SStefano Zampini {
307c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3088629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
309c8587f34SStefano Zampini   PetscErrorCode ierr;
310c8587f34SStefano Zampini 
311c8587f34SStefano Zampini   PetscFunctionBegin;
312f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
3135e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
314c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
315c8587f34SStefano Zampini 
316684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
3170fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
318684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
319c8587f34SStefano Zampini 
320c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
321b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
322c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
323c8587f34SStefano Zampini   }
324c8587f34SStefano Zampini 
3258629588bSStefano Zampini   /*
3268629588bSStefano Zampini      Setup local correction and local part of coarse basis.
3278629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
3288629588bSStefano Zampini   */
32947f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
3308629588bSStefano Zampini 
3318629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
3328629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
3338629588bSStefano Zampini 
3348629588bSStefano Zampini   /* free */
3358629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
336c8587f34SStefano Zampini   PetscFunctionReturn(0);
337c8587f34SStefano Zampini }
338c8587f34SStefano Zampini 
339c8587f34SStefano Zampini #undef __FUNCT__
340674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
341674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
342674ae819SStefano Zampini {
343674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
344674ae819SStefano Zampini   PetscErrorCode ierr;
345674ae819SStefano Zampini 
346674ae819SStefano Zampini   PetscFunctionBegin;
347674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
348674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
349674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
350674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
351785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
352674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
353f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
354f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
355785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
35663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
35763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
358674ae819SStefano Zampini   PetscFunctionReturn(0);
359674ae819SStefano Zampini }
360674ae819SStefano Zampini 
361674ae819SStefano Zampini #undef __FUNCT__
362674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
363674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
364674ae819SStefano Zampini {
365674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
366674ae819SStefano Zampini   PetscErrorCode ierr;
367674ae819SStefano Zampini 
368674ae819SStefano Zampini   PetscFunctionBegin;
369b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
370674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
371674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
372674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
373b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
374674ae819SStefano Zampini   PetscFunctionReturn(0);
375674ae819SStefano Zampini }
376674ae819SStefano Zampini 
377674ae819SStefano Zampini #undef __FUNCT__
378674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
379674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
380674ae819SStefano Zampini {
381674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
38206656605SStefano Zampini   PetscScalar    *array;
383674ae819SStefano Zampini   PetscErrorCode ierr;
384674ae819SStefano Zampini 
385674ae819SStefano Zampini   PetscFunctionBegin;
386674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
387674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
38806656605SStefano Zampini   ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
38906656605SStefano Zampini   ierr = PetscFree(array);CHKERRQ(ierr);
390674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
391674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
39215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
39315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
394674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
395674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
39606656605SStefano Zampini   if (pcbddc->local_auxmat2) {
39706656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
39806656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
39906656605SStefano Zampini   }
400674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
40106656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
402674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
403674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
4048ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
405674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
406674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
407674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
408f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
409f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
410f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
411f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
412727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
413f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
41470cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
4156e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
416674ae819SStefano Zampini   PetscFunctionReturn(0);
417674ae819SStefano Zampini }
418674ae819SStefano Zampini 
419674ae819SStefano Zampini #undef __FUNCT__
420f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
421f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
4226bfb1811SStefano Zampini {
4236bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4246bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4256bfb1811SStefano Zampini   VecType        impVecType;
426e9189074SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
4276bfb1811SStefano Zampini   PetscErrorCode ierr;
4286bfb1811SStefano Zampini 
4296bfb1811SStefano Zampini   PetscFunctionBegin;
430f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
431f4ddd8eeSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
432f4ddd8eeSStefano Zampini   }
433e7b262bdSStefano Zampini   /* get sizes */
434e9189074SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->n_actual_vertices;
435e9189074SStefano Zampini   n_R = pcis->n-pcbddc->n_actual_vertices;
4366bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
437e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
438e7b262bdSStefano Zampini   /* R nodes */
439e7b262bdSStefano Zampini   old_size = -1;
440e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
441e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
442e7b262bdSStefano Zampini   }
443e7b262bdSStefano Zampini   if (n_R != old_size) {
444e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
445e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
4466bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
4476bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
4486bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
4496bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
450e7b262bdSStefano Zampini   }
451e7b262bdSStefano Zampini   /* local primal dofs */
452e7b262bdSStefano Zampini   old_size = -1;
453e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
454e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
455e7b262bdSStefano Zampini   }
456e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
457e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
45883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
459e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
4606bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
461e7b262bdSStefano Zampini   }
462e7b262bdSStefano Zampini   /* local explicit constraints */
463e7b262bdSStefano Zampini   old_size = -1;
464e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
465e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
466e7b262bdSStefano Zampini   }
467e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
468e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
46983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
47083b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
47183b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
47283b7ccabSStefano Zampini   }
4736bfb1811SStefano Zampini   PetscFunctionReturn(0);
4746bfb1811SStefano Zampini }
4756bfb1811SStefano Zampini 
4766bfb1811SStefano Zampini #undef __FUNCT__
47747f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
47847f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
47988ebb749SStefano Zampini {
48025084f0cSStefano Zampini   PetscErrorCode         ierr;
48125084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
48288ebb749SStefano Zampini   PC_IS*                 pcis = (PC_IS*)pc->data;
48388ebb749SStefano Zampini   PC_BDDC*               pcbddc = (PC_BDDC*)pc->data;
48425084f0cSStefano Zampini   /* submatrices of local problem */
48588ebb749SStefano Zampini   Mat                    A_RV,A_VR,A_VV;
48606656605SStefano Zampini   /* submatrices of local coarse problem */
48706656605SStefano Zampini   Mat                    S_VV,S_CV,S_VC,S_CC;
48825084f0cSStefano Zampini   /* working matrices */
48906656605SStefano Zampini   Mat                    C_CR;
49025084f0cSStefano Zampini   /* additional working stuff */
49106656605SStefano Zampini   PC                     pc_R;
49206656605SStefano Zampini   Mat                    F;
49306656605SStefano Zampini   PetscBool              isLU,isCHOL,isILU;
49406656605SStefano Zampini 
49525084f0cSStefano Zampini   PetscScalar            *coarse_submat_vals; /* TODO: use a PETSc matrix */
49606656605SStefano Zampini   PetscScalar            *work;
49706656605SStefano Zampini   PetscInt               *idx_V_B;
49806656605SStefano Zampini   PetscInt               n,n_vertices,n_constraints;
49906656605SStefano Zampini   PetscInt               i,n_R,n_D,n_B;
500b9d89cd5SStefano Zampini   PetscBool              unsymmetric_check;
50145a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
50288ebb749SStefano Zampini   MatType                impMatType;
50325084f0cSStefano Zampini   /* some shortcuts to scalars */
50406656605SStefano Zampini   PetscScalar            one=1.0,m_one=-1.0;
50588ebb749SStefano Zampini 
50688ebb749SStefano Zampini   PetscFunctionBegin;
507e9189074SStefano Zampini   /* get number of vertices (corners plus constraints with change of basis)
508e9189074SStefano Zampini      pcbddc->n_actual_vertices stores the actual number of vertices, pcbddc->n_vertices the number of corners computed */
509e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
51088ebb749SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
51188ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
51288ebb749SStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
51388ebb749SStefano Zampini   n_R = pcis->n-n_vertices;
51488ebb749SStefano Zampini 
51588ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
51688ebb749SStefano Zampini   impMatType = MATSEQDENSE;
51788ebb749SStefano Zampini 
51888ebb749SStefano Zampini   /* vertices in boundary numbering */
519785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
5205e8657edSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->primal_indices_local_idxs,&i,idx_V_B);CHKERRQ(ierr);
52188ebb749SStefano Zampini   if (i != n_vertices) {
52222d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
52388ebb749SStefano Zampini   }
52488ebb749SStefano Zampini 
52506656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
52606656605SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
52706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
52806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
52906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
53006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
53106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
53206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
53306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
53406656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
53506656605SStefano Zampini 
53606656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
53706656605SStefano Zampini   /* allocate workspace */
53806656605SStefano Zampini   n = 0;
53906656605SStefano Zampini   if (n_constraints) {
54006656605SStefano Zampini     n += n_R*n_constraints;
54106656605SStefano Zampini   }
54206656605SStefano Zampini   if (n_vertices) {
54306656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
54406656605SStefano Zampini   }
54506656605SStefano Zampini   if (!pcbddc->issym) {
54606656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
54706656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
54806656605SStefano Zampini   }
54906656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
55006656605SStefano Zampini 
55106656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
55206656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
55306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
55406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
55506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
55606656605SStefano Zampini   if (isLU || isILU || isCHOL) {
55706656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
55806656605SStefano Zampini   } else {
55906656605SStefano Zampini     F = NULL;
56006656605SStefano Zampini   }
56106656605SStefano Zampini 
56288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
56388ebb749SStefano Zampini   if (n_constraints) {
56406656605SStefano Zampini     Mat M1,M2,M3;
56506656605SStefano Zampini     IS  is_aux;
566f4ddd8eeSStefano Zampini     /* see if we can save some allocations */
567f4ddd8eeSStefano Zampini     if (pcbddc->local_auxmat2) {
568f4ddd8eeSStefano Zampini       PetscInt on_R,on_constraints;
569f4ddd8eeSStefano Zampini       ierr = MatGetSize(pcbddc->local_auxmat2,&on_R,&on_constraints);CHKERRQ(ierr);
570f4ddd8eeSStefano Zampini       if (on_R != n_R || on_constraints != n_constraints) {
57106656605SStefano Zampini         PetscScalar *marray;
57206656605SStefano Zampini 
57306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->local_auxmat2,&marray);CHKERRQ(ierr);
57406656605SStefano Zampini         ierr = PetscFree(marray);CHKERRQ(ierr);
575f4ddd8eeSStefano Zampini         ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
576f4ddd8eeSStefano Zampini         ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
577f4ddd8eeSStefano Zampini       }
578f4ddd8eeSStefano Zampini     }
57945a1bb75SStefano Zampini     /* auxiliary matrices */
580f4ddd8eeSStefano Zampini     if (!pcbddc->local_auxmat2) {
58106656605SStefano Zampini       PetscScalar *marray;
58206656605SStefano Zampini 
58306656605SStefano Zampini       ierr = PetscMalloc1(2*n_R*n_constraints,&marray);CHKERRQ(ierr);
58406656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,marray,&pcbddc->local_auxmat2);CHKERRQ(ierr);
58506656605SStefano Zampini       marray += n_R*n_constraints;
58606656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_R,marray,&pcbddc->local_auxmat1);CHKERRQ(ierr);
587f4ddd8eeSStefano Zampini     }
58888ebb749SStefano Zampini 
58925084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
59025084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
5918ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
59225084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
59388ebb749SStefano Zampini 
59488ebb749SStefano Zampini     /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
59506656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
59688ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
59706656605SStefano Zampini       const PetscScalar *row_cmat_values;
59806656605SStefano Zampini       const PetscInt    *row_cmat_indices;
59906656605SStefano Zampini       PetscInt          size_of_constraint,j;
60088ebb749SStefano Zampini 
60106656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
60206656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
60306656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
60406656605SStefano Zampini       }
60506656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
60606656605SStefano Zampini     }
60706656605SStefano Zampini     if (F) {
60806656605SStefano Zampini       Mat B;
60906656605SStefano Zampini 
61006656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
61106656605SStefano Zampini       ierr = MatMatSolve(F,B,pcbddc->local_auxmat2);CHKERRQ(ierr);
61206656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
61306656605SStefano Zampini     } else {
61406656605SStefano Zampini       PetscScalar *xarray;
61506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&xarray);CHKERRQ(ierr);
61606656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
61706656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
61806656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,xarray+i*n_R);CHKERRQ(ierr);
61906656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
62006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
62106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
62206656605SStefano Zampini       }
62306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&xarray);CHKERRQ(ierr);
62406656605SStefano Zampini     }
62506656605SStefano Zampini 
62606656605SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
62706656605SStefano Zampini     ierr = MatConvert(C_CR,impMatType,MAT_REUSE_MATRIX,&C_CR);CHKERRQ(ierr);
62825084f0cSStefano Zampini     ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
62906656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
63006656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
63125084f0cSStefano Zampini     ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
63206656605SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,m_one);CHKERRQ(ierr);
63306656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
63425084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
63525084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
63625084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
63706656605SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CR} needed by BDDC application in KSP and in preproc */
638f4ddd8eeSStefano Zampini     ierr = MatMatMult(M1,C_CR,MAT_REUSE_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
63906656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
64006656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
64188ebb749SStefano Zampini   }
64288ebb749SStefano Zampini 
64388ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
64488ebb749SStefano Zampini   if (n_vertices) {
64506656605SStefano Zampini     Mat       newmat;
64606656605SStefano Zampini     IS        is_aux;
6473a50541eSStefano Zampini     PetscInt  ibs,mbs;
6483a50541eSStefano Zampini     PetscBool issbaij;
6493a50541eSStefano Zampini 
6503a50541eSStefano Zampini     ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
6519577ea80SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
6529577ea80SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
6533a50541eSStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ */
6549577ea80SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
6559577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
6569577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
6579577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
6589577ea80SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
6599577ea80SStefano Zampini     } else {
6603a50541eSStefano Zampini       /* this is safe */
6619577ea80SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
6623a50541eSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
6633a50541eSStefano Zampini       if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
6643a50541eSStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
6653a50541eSStefano Zampini         ierr = MatGetSubMatrix(newmat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
66606656605SStefano Zampini         ierr = MatTranspose(A_VR,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
6673a50541eSStefano Zampini         ierr = MatDestroy(&newmat);CHKERRQ(ierr);
6683a50541eSStefano Zampini       } else {
6699577ea80SStefano Zampini         ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
6709577ea80SStefano Zampini         ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
6719577ea80SStefano Zampini       }
6723a50541eSStefano Zampini     }
67325084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
67488ebb749SStefano Zampini   }
67588ebb749SStefano Zampini 
67688ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
677f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
67806656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
67906656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
68006656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
68106656605SStefano Zampini     }
682f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
68306656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
68406656605SStefano Zampini       PetscScalar *marray;
68506656605SStefano Zampini 
68606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
68706656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
688f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
689f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
690f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
691f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
692f4ddd8eeSStefano Zampini     }
693f4ddd8eeSStefano Zampini   }
69406656605SStefano Zampini 
695f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
69606656605SStefano Zampini     PetscScalar *marray;
69788ebb749SStefano Zampini 
69806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
6998eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
70006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
70188ebb749SStefano Zampini     }
702b9d89cd5SStefano Zampini     if (!pcbddc->issym) {
70306656605SStefano Zampini       n *= 2;
704f4ddd8eeSStefano Zampini     }
70506656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
70606656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
70706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
70806656605SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
70906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
71006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
71188ebb749SStefano Zampini     }
71206656605SStefano Zampini     if (!pcbddc->issym) {
71306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
71406656605SStefano Zampini       if (pcbddc->switch_static) {
71506656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
71606656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
71788ebb749SStefano Zampini       }
71888ebb749SStefano Zampini     } else {
719c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
720c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
72106656605SStefano Zampini       if (pcbddc->switch_static) {
722c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
723c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
724c0553b1fSStefano Zampini       }
72588ebb749SStefano Zampini     }
72606656605SStefano Zampini   }
72706656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
72806656605SStefano Zampini   /* vertices */
72906656605SStefano Zampini   if (n_vertices) {
73006656605SStefano Zampini     Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
73106656605SStefano Zampini     PetscScalar  *x,*y;
73206656605SStefano Zampini     PetscBLASInt B_N,B_one = 1;
73306656605SStefano Zampini 
73406656605SStefano Zampini     ierr = PetscMemzero(work,2*n_R*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
73506656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
73606656605SStefano Zampini     ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
73706656605SStefano Zampini     if (F) {
73806656605SStefano Zampini       ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
73906656605SStefano Zampini     } else {
74006656605SStefano Zampini       ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
74106656605SStefano Zampini       for (i=0;i<n_vertices;i++) {
74206656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
74306656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
74406656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
74506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
74606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
74706656605SStefano Zampini       }
74806656605SStefano Zampini       ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
74906656605SStefano Zampini     }
75006656605SStefano Zampini     ierr = MatScale(A_RRmA_RV,m_one);CHKERRQ(ierr);
75106656605SStefano Zampini     /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
75206656605SStefano Zampini     if (n_constraints) {
75306656605SStefano Zampini       Mat B;
75406656605SStefano Zampini       ierr = MatMatMult(pcbddc->local_auxmat1,A_RRmA_RV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
75506656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
75606656605SStefano Zampini       ierr = MatMatMult(pcbddc->local_auxmat2,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
75706656605SStefano Zampini       ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
75806656605SStefano Zampini       ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
75906656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
76006656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
76106656605SStefano Zampini     }
76206656605SStefano Zampini     ierr = MatConvert(A_VR,impMatType,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
76306656605SStefano Zampini     ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
76406656605SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
76506656605SStefano Zampini     ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
76606656605SStefano Zampini     ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
76706656605SStefano Zampini     ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
76806656605SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
76906656605SStefano Zampini     ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
77006656605SStefano Zampini     ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
77106656605SStefano Zampini     ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
77206656605SStefano Zampini     ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
77306656605SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
77406656605SStefano Zampini     /* coarse basis functions */
77506656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
77606656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
77706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
77806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
77906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
78006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
78106656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
78206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
78306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
78406656605SStefano Zampini 
78506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
78606656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
78706656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
78806656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
78906656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
79006656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
79106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
79206656605SStefano Zampini       }
79306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
79406656605SStefano Zampini     }
79506656605SStefano Zampini     ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
79606656605SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
79706656605SStefano Zampini   }
79806656605SStefano Zampini 
79906656605SStefano Zampini   if (n_constraints) {
80006656605SStefano Zampini     Mat B;
80106656605SStefano Zampini 
80206656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
80306656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
80406656605SStefano Zampini     ierr = MatMatMult(pcbddc->local_auxmat2,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
80506656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
80606656605SStefano Zampini     if (n_vertices) {
80706656605SStefano Zampini       ierr = MatMatMult(A_VR,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_VC);CHKERRQ(ierr);
80806656605SStefano Zampini     }
80906656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
81006656605SStefano Zampini     /* coarse basis functions */
81106656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
81206656605SStefano Zampini       PetscScalar *y;
81306656605SStefano Zampini 
81406656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
81506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
81606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
81706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
81806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
81906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
82006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
82106656605SStefano Zampini 
82206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
82306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
82406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
82506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
82606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
82706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
82806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
82906656605SStefano Zampini       }
83006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
83106656605SStefano Zampini     }
83206656605SStefano Zampini   }
83306656605SStefano Zampini 
83406656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
83506656605SStefano Zampini   if (!pcbddc->issym) {
83606656605SStefano Zampini     Mat B,X;
83706656605SStefano Zampini 
83806656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,pcbddc->local_primal_size,work,&B);CHKERRQ(ierr);
83906656605SStefano Zampini 
84006656605SStefano Zampini     if (n_constraints) {
84106656605SStefano Zampini       Mat S_VCT,S_CCT,B_C;
84206656605SStefano Zampini 
84306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
84406656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
84506656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
84606656605SStefano Zampini       if (n_vertices) {
84706656605SStefano Zampini         Mat B_V;
84806656605SStefano Zampini 
84906656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
85006656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
85106656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
85206656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
85306656605SStefano Zampini       }
85406656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
85506656605SStefano Zampini     }
85606656605SStefano Zampini     if (n_vertices) {
85706656605SStefano Zampini       Mat          A_VRT;
85806656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
85906656605SStefano Zampini 
86006656605SStefano Zampini       if (!n_constraints) { /* if there are no constraints, reset work */
86106656605SStefano Zampini         ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
86206656605SStefano Zampini       }
86306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+pcbddc->local_primal_size*n_R,&A_VRT);CHKERRQ(ierr);
86406656605SStefano Zampini       ierr = MatTranspose(A_VR,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
86506656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
86606656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,work+pcbddc->local_primal_size*n_R,&B_one,work,&B_one));
86706656605SStefano Zampini     }
86806656605SStefano Zampini 
86906656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,pcbddc->local_primal_size,work+pcbddc->local_primal_size*n_R,&X);CHKERRQ(ierr);
87006656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
87106656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
87206656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
87306656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
87406656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
87506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
87606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
87706656605SStefano Zampini       }
87806656605SStefano Zampini     } else {
87906656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
88006656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
88106656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
88206656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
88306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
88406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
88506656605SStefano Zampini       }
88606656605SStefano Zampini     }
88706656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
88806656605SStefano Zampini     /* coarse basis functions */
88906656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
89006656605SStefano Zampini       PetscScalar *y;
89106656605SStefano Zampini 
89206656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
89306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
89406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
89506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
89606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
89706656605SStefano Zampini       if (i<n_vertices) {
89806656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
89906656605SStefano Zampini       }
90006656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
90106656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
90206656605SStefano Zampini 
90306656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
90406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
90506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
90606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
90706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
90806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
90906656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
91006656605SStefano Zampini       }
91106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
91206656605SStefano Zampini     }
91306656605SStefano Zampini     ierr = MatDestroy(&X);CHKERRQ(ierr);
91406656605SStefano Zampini   }
91506656605SStefano Zampini 
91688ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
91706656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
91806656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
91906656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
92006656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
92188ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
92288ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
92388ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
92425084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
92588ebb749SStefano Zampini     Mat         coarse_sub_mat;
92625084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
92788ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
92888ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
92988ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
93088ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
93188ebb749SStefano Zampini     PetscReal   real_value;
93288ebb749SStefano Zampini 
93388ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
93488ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
93588ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
93688ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
93788ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
93888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
939c0553b1fSStefano Zampini     if (unsymmetric_check) {
94088ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
94188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
94288ebb749SStefano Zampini     }
94388ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
94488ebb749SStefano Zampini 
94525084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
94606656605SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation\n");CHKERRQ(ierr);
94725084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
948c0553b1fSStefano Zampini     if (unsymmetric_check) {
94988ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
95088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
95188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
95288ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
95388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
95488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
95588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
95688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
95788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
95888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
95988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
96088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
96188ebb749SStefano Zampini     } else {
96288ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
96388ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
96488ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
96588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
96688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
96788ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
96888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
96988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
97088ebb749SStefano Zampini     }
97188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
97288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
97388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
97488ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
97581d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
97688ebb749SStefano Zampini     ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
97706656605SStefano Zampini 
9780fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
97906656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
98025084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
98188ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
98288ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
98388ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
98488ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
98588ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
98688ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
98788ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
98888ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
98988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
99088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
991c0553b1fSStefano Zampini     if (unsymmetric_check) {
99288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
99388ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
99488ebb749SStefano Zampini     }
99588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
99688ebb749SStefano Zampini   }
99706656605SStefano Zampini 
99888ebb749SStefano Zampini   /* free memory */
99906656605SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
100088ebb749SStefano Zampini   if (n_vertices) {
100188ebb749SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
100288ebb749SStefano Zampini   }
100388ebb749SStefano Zampini   if (n_constraints) {
100488ebb749SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
100588ebb749SStefano Zampini   }
10068629588bSStefano Zampini   /* get back data */
10078629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
100888ebb749SStefano Zampini   PetscFunctionReturn(0);
100988ebb749SStefano Zampini }
101088ebb749SStefano Zampini 
101188ebb749SStefano Zampini #undef __FUNCT__
1012d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1013b96c3477SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, MatStructure reuse, Mat* B)
1014d65f70fdSStefano Zampini {
1015d65f70fdSStefano Zampini   Mat            *work_mat;
1016d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1017d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1018d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1019d65f70fdSStefano Zampini   PetscErrorCode ierr;
1020d65f70fdSStefano Zampini 
1021d65f70fdSStefano Zampini   PetscFunctionBegin;
1022d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1023d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1024d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1025d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1026d65f70fdSStefano Zampini 
1027d65f70fdSStefano Zampini   if (!rsorted) {
1028d65f70fdSStefano Zampini     const PetscInt *idxs;
1029d65f70fdSStefano Zampini     PetscInt *idxs_sorted,i;
1030d65f70fdSStefano Zampini 
1031d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1032d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1033d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1034d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1035d65f70fdSStefano Zampini     }
1036d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1037d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1038d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1039d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1040d65f70fdSStefano Zampini     }
1041d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1042d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1043d65f70fdSStefano Zampini   } else {
1044d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1045d65f70fdSStefano Zampini     isrow_s = isrow;
1046d65f70fdSStefano Zampini   }
1047d65f70fdSStefano Zampini 
1048d65f70fdSStefano Zampini   if (!csorted) {
1049d65f70fdSStefano Zampini     if (isrow == iscol) {
1050d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1051d65f70fdSStefano Zampini       iscol_s = isrow_s;
1052d65f70fdSStefano Zampini     } else {
1053d65f70fdSStefano Zampini       const PetscInt *idxs;
1054d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1055d65f70fdSStefano Zampini 
1056d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1057d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1058d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1059d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1060d65f70fdSStefano Zampini       }
1061d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1062d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1063d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1064d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1065d65f70fdSStefano Zampini       }
1066d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1067d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1068d65f70fdSStefano Zampini     }
1069d65f70fdSStefano Zampini   } else {
1070d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1071d65f70fdSStefano Zampini     iscol_s = iscol;
1072d65f70fdSStefano Zampini   }
1073d65f70fdSStefano Zampini 
1074b96c3477SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,reuse,&work_mat);CHKERRQ(ierr);
1075d65f70fdSStefano Zampini 
1076d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1077d65f70fdSStefano Zampini     Mat      new_mat;
1078d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1079d65f70fdSStefano Zampini 
1080d65f70fdSStefano Zampini     if (!rsorted) {
1081d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1082d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1083d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1084d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1085d65f70fdSStefano Zampini       }
1086d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1087d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1088d65f70fdSStefano Zampini     } else {
1089d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1090d65f70fdSStefano Zampini     }
1091d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1092d65f70fdSStefano Zampini 
1093d65f70fdSStefano Zampini     if (!csorted) {
1094d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1095d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1096d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1097d65f70fdSStefano Zampini       } else {
1098d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1099d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1100d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1101d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1102d65f70fdSStefano Zampini         }
1103d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1104d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1105d65f70fdSStefano Zampini       }
1106d65f70fdSStefano Zampini     } else {
1107d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1108d65f70fdSStefano Zampini     }
1109d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1110d65f70fdSStefano Zampini 
1111d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1112d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1113d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1114d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1115d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1116d65f70fdSStefano Zampini   }
1117d65f70fdSStefano Zampini 
1118d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1119d65f70fdSStefano Zampini   *B = work_mat[0];
1120d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1121d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1122d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1123d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1124d65f70fdSStefano Zampini }
1125d65f70fdSStefano Zampini 
1126d65f70fdSStefano Zampini #undef __FUNCT__
11275e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
11285e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1129aa0d41d4SStefano Zampini {
1130aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
11315e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1132d65f70fdSStefano Zampini   Mat            new_mat;
11335e8657edSStefano Zampini   IS             is_local,is_global;
1134d65f70fdSStefano Zampini   PetscInt       local_size;
1135d65f70fdSStefano Zampini   PetscBool      isseqaij;
1136aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1137aa0d41d4SStefano Zampini 
1138aa0d41d4SStefano Zampini   PetscFunctionBegin;
1139aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
11405e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
11415e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1142906d46d4SStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(matis->mapping,is_local,&is_global);CHKERRQ(ierr);
1143906d46d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1144b96c3477SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,MAT_INITIAL_MATRIX,&new_mat);CHKERRQ(ierr);
1145906d46d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1146906d46d4SStefano Zampini 
1147906d46d4SStefano Zampini   /* check */
1148906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
1149906d46d4SStefano Zampini     Vec       x,x_change;
1150906d46d4SStefano Zampini     PetscReal error;
1151906d46d4SStefano Zampini 
11525e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1153906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
11545e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
11555e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11565e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1157d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
11585e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11595e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1160906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1161906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1162906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1163906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1164906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
1165906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1166906d46d4SStefano Zampini   }
1167906d46d4SStefano Zampini 
116822d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
11699b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
117022d5777bSStefano Zampini   if (isseqaij) {
1171d65f70fdSStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1172aa0d41d4SStefano Zampini   } else {
1173aa0d41d4SStefano Zampini     Mat work_mat;
1174aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1175d65f70fdSStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1176aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
1177aa0d41d4SStefano Zampini   }
1178d65f70fdSStefano Zampini   ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
117945a1bb75SStefano Zampini   /*
118045a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1181d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
118245a1bb75SStefano Zampini   */
1183d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
1184aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
1185aa0d41d4SStefano Zampini }
1186aa0d41d4SStefano Zampini 
1187aa0d41d4SStefano Zampini #undef __FUNCT__
1188a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
11898ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
1190a64d13efSStefano Zampini {
1191a64d13efSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
1192a64d13efSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
11938ce42a96SStefano Zampini   IS             is_aux1,is_aux2;
1194e9189074SStefano Zampini   PetscInt       *aux_array1,*aux_array2,*is_indices,*idx_R_local;
11953a50541eSStefano Zampini   PetscInt       n_vertices,i,j,n_R,n_D,n_B;
11963a50541eSStefano Zampini   PetscInt       vbs,bs;
11974641a718SStefano Zampini   PetscBT        bitmask;
1198a64d13efSStefano Zampini   PetscErrorCode ierr;
1199a64d13efSStefano Zampini 
1200a64d13efSStefano Zampini   PetscFunctionBegin;
1201b23d619eSStefano Zampini   /*
1202b23d619eSStefano Zampini     No need to setup local scatters if
1203b23d619eSStefano Zampini       - primal space is unchanged
1204b23d619eSStefano Zampini         AND
1205b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
1206b23d619eSStefano Zampini         AND
1207b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
1208b23d619eSStefano Zampini   */
1209b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
1210f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
1211f4ddd8eeSStefano Zampini   }
1212f4ddd8eeSStefano Zampini   /* destroy old objects */
1213f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1214f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1215f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1216a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
1217a64d13efSStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
1218e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
12194641a718SStefano Zampini   /* create auxiliary bitmask */
12204641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
12214641a718SStefano Zampini   for (i=0;i<n_vertices;i++) {
1222e9189074SStefano Zampini     ierr = PetscBTSet(bitmask,pcbddc->primal_indices_local_idxs[i]);CHKERRQ(ierr);
12234641a718SStefano Zampini   }
12243a50541eSStefano Zampini 
1225a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
1226854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
1227a64d13efSStefano Zampini   for (i=0, n_R=0; i<pcis->n; i++) {
12284641a718SStefano Zampini     if (!PetscBTLookup(bitmask,i)) {
1229a64d13efSStefano Zampini       idx_R_local[n_R] = i;
1230a64d13efSStefano Zampini       n_R++;
1231a64d13efSStefano Zampini     }
1232a64d13efSStefano Zampini   }
12333a50541eSStefano Zampini 
12343a50541eSStefano Zampini   /* Block code */
12353a50541eSStefano Zampini   vbs = 1;
12363a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
12373a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
12383a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
12393a50541eSStefano Zampini     PetscInt  *vary;
12403a50541eSStefano Zampini     /* Verify if the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
1241785e854fSJed Brown     ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
12423a50541eSStefano Zampini     ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
1243e9189074SStefano Zampini     for (i=0; i<n_vertices; i++) vary[pcbddc->primal_indices_local_idxs[i]/bs]++;
12443a50541eSStefano Zampini     for (i=0; i<n_vertices; i++) {
12453a50541eSStefano Zampini       if (vary[i]!=0 && vary[i]!=bs) {
12463a50541eSStefano Zampini         is_blocked = PETSC_FALSE;
12473a50541eSStefano Zampini         break;
12483a50541eSStefano Zampini       }
12493a50541eSStefano Zampini     }
12503a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
12513a50541eSStefano Zampini       vbs = bs;
12523a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
12533a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
12543a50541eSStefano Zampini       }
12553a50541eSStefano Zampini     }
12563a50541eSStefano Zampini     ierr = PetscFree(vary);CHKERRQ(ierr);
12573a50541eSStefano Zampini   }
12583a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
12593a50541eSStefano Zampini   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
1260a64d13efSStefano Zampini 
1261a64d13efSStefano Zampini   /* print some info if requested */
1262a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
1263a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1264a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
12650fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1266a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1267a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
12683a50541eSStefano 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);
1269a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
1270a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1271a64d13efSStefano Zampini   }
1272a64d13efSStefano Zampini 
1273a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
12743a50541eSStefano Zampini   ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1275854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
1276854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
1277a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
12784641a718SStefano Zampini   for (i=0; i<n_D; i++) {
12794641a718SStefano Zampini     ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
12804641a718SStefano Zampini   }
1281a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1282a64d13efSStefano Zampini   for (i=0, j=0; i<n_R; i++) {
12834641a718SStefano Zampini     if (!PetscBTLookup(bitmask,idx_R_local[i])) {
12844641a718SStefano Zampini       aux_array1[j++] = i;
1285a64d13efSStefano Zampini     }
1286a64d13efSStefano Zampini   }
1287a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1288a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1289a64d13efSStefano Zampini   for (i=0, j=0; i<n_B; i++) {
12904641a718SStefano Zampini     if (!PetscBTLookup(bitmask,is_indices[i])) {
12914641a718SStefano Zampini       aux_array2[j++] = i;
1292a64d13efSStefano Zampini     }
1293a64d13efSStefano Zampini   }
1294a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1295a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
1296a64d13efSStefano Zampini   ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1297a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1298a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1299a64d13efSStefano Zampini 
13008eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
1301785e854fSJed Brown     ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
1302a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
13034641a718SStefano Zampini       if (PetscBTLookup(bitmask,idx_R_local[i])) {
13044641a718SStefano Zampini         aux_array1[j++] = i;
1305a64d13efSStefano Zampini       }
1306a64d13efSStefano Zampini     }
1307a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1308a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1309a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1310a64d13efSStefano Zampini   }
13114641a718SStefano Zampini   ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
13123a50541eSStefano Zampini   ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1313a64d13efSStefano Zampini   PetscFunctionReturn(0);
1314a64d13efSStefano Zampini }
1315a64d13efSStefano Zampini 
1316304d26faSStefano Zampini 
1317304d26faSStefano Zampini #undef __FUNCT__
1318304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1319684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1320304d26faSStefano Zampini {
1321304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1322304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1323304d26faSStefano Zampini   PC             pc_temp;
1324304d26faSStefano Zampini   Mat            A_RR;
1325f4ddd8eeSStefano Zampini   MatReuse       reuse;
1326304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1327304d26faSStefano Zampini   PetscReal      value;
1328af732b37SStefano Zampini   PetscInt       n_D,n_R,ibs,mbs;
13299577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1330304d26faSStefano Zampini   PetscErrorCode ierr;
1331e604994aSStefano Zampini   /* prefixes stuff */
1332312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1333e604994aSStefano Zampini   size_t         len;
1334304d26faSStefano Zampini 
1335304d26faSStefano Zampini   PetscFunctionBegin;
1336304d26faSStefano Zampini 
1337e604994aSStefano Zampini   /* compute prefixes */
1338e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1339e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1340e604994aSStefano Zampini   if (!pcbddc->current_level) {
1341e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1342e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1343e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1344e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1345e604994aSStefano Zampini   } else {
1346e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1347312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1348e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1349e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1350312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1351312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
135234d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
135334d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1354e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1355e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1356e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1357e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1358e604994aSStefano Zampini   }
1359e604994aSStefano Zampini 
1360304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1361684f6988SStefano Zampini   if (dirichlet) {
1362ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
13638ce42a96SStefano Zampini     ierr = ISGetSize(pcis->is_I_local,&n_D);CHKERRQ(ierr);
1364304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1365304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1366304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1367304d26faSStefano Zampini       /* default */
1368304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1369e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
13709577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1371304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
13729577ea80SStefano Zampini       if (issbaij) {
13739577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
13749577ea80SStefano Zampini       } else {
1375304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13769577ea80SStefano Zampini       }
1377304d26faSStefano Zampini       /* Allow user's customization */
1378304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1379304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1380304d26faSStefano Zampini     }
1381d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1382304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1383304d26faSStefano Zampini     if (!n_D) {
1384304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1385304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1386304d26faSStefano Zampini     }
1387304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1388304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1389304d26faSStefano Zampini     /* set ksp_D into pcis data */
1390304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1391304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1392304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1393684f6988SStefano Zampini   }
1394304d26faSStefano Zampini 
1395304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1396684f6988SStefano Zampini   A_RR = 0;
1397684f6988SStefano Zampini   if (neumann) {
1398f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
13998ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1400f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1401f4ddd8eeSStefano Zampini       PetscInt nn_R;
140281d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1403f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1404f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1405f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1406f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1407f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1408f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1409f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1410727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1411f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1412f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1413f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1414f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1415f4ddd8eeSStefano Zampini         }
1416f4ddd8eeSStefano Zampini       }
1417f4ddd8eeSStefano Zampini       /* last check */
1418d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1419f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1420f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1421f4ddd8eeSStefano Zampini       }
1422f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1423f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1424f4ddd8eeSStefano Zampini     }
1425f4ddd8eeSStefano Zampini     /* extract A_RR */
1426af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1427af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
14283a50541eSStefano Zampini     if (ibs != mbs) {
1429af732b37SStefano Zampini       Mat newmat;
1430af732b37SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
1431f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1432af732b37SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
1433af732b37SStefano Zampini     } else {
1434f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1435af732b37SStefano Zampini     }
1436f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
1437304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1438304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1439304d26faSStefano Zampini       /* default */
1440304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1441e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
1442304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
14439577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
14449577ea80SStefano Zampini       if (issbaij) {
14459577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
14469577ea80SStefano Zampini       } else {
1447304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
14489577ea80SStefano Zampini       }
1449304d26faSStefano Zampini       /* Allow user's customization */
1450304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1451304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1452304d26faSStefano Zampini     }
1453d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
1454304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1455304d26faSStefano Zampini     if (!n_R) {
1456304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1457304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1458304d26faSStefano Zampini     }
1459304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
1460304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1461684f6988SStefano Zampini   }
1462304d26faSStefano Zampini 
1463304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
14640fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
1465684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
1466684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1467684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1468684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1469684f6988SStefano Zampini     }
1470684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
14710fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
14720fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
14730fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
14740fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
14750fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
1476304d26faSStefano Zampini       /* need to be adapted? */
1477b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1478b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1479b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
1480304d26faSStefano Zampini       /* print info */
1481304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1482e604994aSStefano 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);
1483304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1484304d26faSStefano Zampini       }
1485b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
14868ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);CHKERRQ(ierr);
1487304d26faSStefano Zampini       }
1488684f6988SStefano Zampini     }
1489684f6988SStefano Zampini     if (neumann) { /* Neumann */
14900fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
14910fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14920fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
14930fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
14940fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
1495304d26faSStefano Zampini       /* need to be adapted? */
1496b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1497b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1498304d26faSStefano Zampini       /* print info */
1499304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1500e604994aSStefano 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);
1501304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1502304d26faSStefano Zampini       }
1503b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
15048ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcbddc->is_R_local);CHKERRQ(ierr);
1505304d26faSStefano Zampini       }
15060fccc4e9SStefano Zampini     }
1507684f6988SStefano Zampini   }
1508304d26faSStefano Zampini   /* free Neumann problem's matrix */
1509304d26faSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1510304d26faSStefano Zampini   PetscFunctionReturn(0);
1511304d26faSStefano Zampini }
1512304d26faSStefano Zampini 
1513304d26faSStefano Zampini #undef __FUNCT__
1514ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
151520c7b377SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec rhs, Vec sol, Vec work, PetscBool applytranspose)
1516674ae819SStefano Zampini {
1517674ae819SStefano Zampini   PetscErrorCode ierr;
1518674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
1519674ae819SStefano Zampini 
1520674ae819SStefano Zampini   PetscFunctionBegin;
152120c7b377SStefano Zampini   if (applytranspose) {
1522674ae819SStefano Zampini     if (pcbddc->local_auxmat1) {
152320c7b377SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,rhs,work);CHKERRQ(ierr);
152420c7b377SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,work,rhs,rhs);CHKERRQ(ierr);
152520c7b377SStefano Zampini     }
152620c7b377SStefano Zampini     ierr = KSPSolveTranspose(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
152720c7b377SStefano Zampini   } else {
152820c7b377SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
152920c7b377SStefano Zampini     if (pcbddc->local_auxmat1) {
153020c7b377SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,sol,work);CHKERRQ(ierr);
153120c7b377SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,work,sol,sol);CHKERRQ(ierr);
153220c7b377SStefano Zampini     }
1533674ae819SStefano Zampini   }
1534674ae819SStefano Zampini   PetscFunctionReturn(0);
1535674ae819SStefano Zampini }
1536674ae819SStefano Zampini 
1537dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
1538674ae819SStefano Zampini #undef __FUNCT__
1539674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
1540dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
1541674ae819SStefano Zampini {
1542674ae819SStefano Zampini   PetscErrorCode ierr;
1543674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1544674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
1545674ae819SStefano Zampini   const PetscScalar zero = 0.0;
1546674ae819SStefano Zampini 
1547674ae819SStefano Zampini   PetscFunctionBegin;
1548dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
1549dc359a40SStefano Zampini   if (applytranspose) {
1550674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
15518eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
1552dc359a40SStefano Zampini   } else {
1553674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
1554674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
155515aaf578SStefano Zampini   }
155612edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
155712edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
155812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
156012edc857SStefano Zampini 
15619f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
156212edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
156312edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
156412edc857SStefano Zampini     if (applytranspose) {
156512edc857SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
156612edc857SStefano Zampini     } else {
156712edc857SStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
156812edc857SStefano Zampini     }
156912edc857SStefano Zampini   }
1570674ae819SStefano Zampini 
1571674ae819SStefano Zampini   /* Local solution on R nodes */
15729f00e9b4SStefano Zampini   if (pcis->n) {
1573674ae819SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
1574674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1575674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15768eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1577674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1578674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1579674ae819SStefano Zampini     }
158020c7b377SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcbddc->vec1_R,pcbddc->vec2_R,pcbddc->vec1_C,applytranspose);CHKERRQ(ierr);
1581674ae819SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1582674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1583674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15848eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1585674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1586674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1587674ae819SStefano Zampini     }
15889f00e9b4SStefano Zampini   }
1589674ae819SStefano Zampini 
15909f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
15919f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
159212edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1593674ae819SStefano Zampini 
1594674ae819SStefano Zampini   /* Sum contributions from two levels */
1595dc359a40SStefano Zampini   if (applytranspose) {
1596dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
1597dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1598dc359a40SStefano Zampini   } else {
1599674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
16008eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1601dc359a40SStefano Zampini   }
1602674ae819SStefano Zampini   PetscFunctionReturn(0);
1603674ae819SStefano Zampini }
1604674ae819SStefano Zampini 
160512edc857SStefano Zampini /* TODO: the following two function can be optimized using VecPlaceArray whenever possible and using overlap flag */
1606674ae819SStefano Zampini #undef __FUNCT__
1607674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
160812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
1609674ae819SStefano Zampini {
1610674ae819SStefano Zampini   PetscErrorCode ierr;
1611674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
161212edc857SStefano Zampini   PetscScalar    *array,*array2;
161312edc857SStefano Zampini   Vec            from,to;
1614674ae819SStefano Zampini 
1615674ae819SStefano Zampini   PetscFunctionBegin;
161612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
161712edc857SStefano Zampini     from = pcbddc->coarse_vec;
161812edc857SStefano Zampini     to = pcbddc->vec1_P;
161912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
162012edc857SStefano Zampini       Vec tvec;
162112edc857SStefano Zampini       PetscInt lsize;
162212edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
162312edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
162412edc857SStefano Zampini       ierr = VecGetArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
162512edc857SStefano Zampini       ierr = VecGetArray(from,&array2);CHKERRQ(ierr);
162612edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
162712edc857SStefano Zampini       ierr = VecRestoreArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
162812edc857SStefano Zampini       ierr = VecRestoreArray(from,&array2);CHKERRQ(ierr);
162912edc857SStefano Zampini     }
163012edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
163112edc857SStefano Zampini     from = pcbddc->vec1_P;
163212edc857SStefano Zampini     to = pcbddc->coarse_vec;
163312edc857SStefano Zampini   }
163412edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
1635674ae819SStefano Zampini   PetscFunctionReturn(0);
1636674ae819SStefano Zampini }
1637674ae819SStefano Zampini 
1638674ae819SStefano Zampini #undef __FUNCT__
1639674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
164012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
1641674ae819SStefano Zampini {
1642674ae819SStefano Zampini   PetscErrorCode ierr;
1643674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
164412edc857SStefano Zampini   PetscScalar    *array,*array2;
164512edc857SStefano Zampini   Vec            from,to;
1646674ae819SStefano Zampini 
1647674ae819SStefano Zampini   PetscFunctionBegin;
164812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
164912edc857SStefano Zampini     from = pcbddc->coarse_vec;
165012edc857SStefano Zampini     to = pcbddc->vec1_P;
165112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
165212edc857SStefano Zampini     from = pcbddc->vec1_P;
165312edc857SStefano Zampini     to = pcbddc->coarse_vec;
165412edc857SStefano Zampini   }
165512edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
165612edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
165712edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
165812edc857SStefano Zampini       Vec tvec;
165912edc857SStefano Zampini       PetscInt lsize;
166012edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
166112edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
166212edc857SStefano Zampini       ierr = VecGetArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
166312edc857SStefano Zampini       ierr = VecGetArray(tvec,&array2);CHKERRQ(ierr);
166412edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
166512edc857SStefano Zampini       ierr = VecRestoreArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
166612edc857SStefano Zampini       ierr = VecRestoreArray(tvec,&array2);CHKERRQ(ierr);
166712edc857SStefano Zampini     }
166812edc857SStefano Zampini   }
1669674ae819SStefano Zampini   PetscFunctionReturn(0);
1670674ae819SStefano Zampini }
1671674ae819SStefano Zampini 
1672984c4197SStefano Zampini /* uncomment for testing purposes */
1673984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
1674674ae819SStefano Zampini #undef __FUNCT__
1675674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
1676674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
1677674ae819SStefano Zampini {
1678674ae819SStefano Zampini   PetscErrorCode    ierr;
1679674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
1680674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1681674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
1682984c4197SStefano Zampini   /* constraint and (optionally) change of basis matrix implemented as SeqAIJ */
1683674ae819SStefano Zampini   MatType           impMatType=MATSEQAIJ;
1684984c4197SStefano Zampini   /* one and zero */
1685984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
1686984c4197SStefano Zampini   /* space to store constraints and their local indices */
1687984c4197SStefano Zampini   PetscScalar       *temp_quadrature_constraint;
1688984c4197SStefano Zampini   PetscInt          *temp_indices,*temp_indices_to_constraint,*temp_indices_to_constraint_B;
1689984c4197SStefano Zampini   /* iterators */
1690984c4197SStefano Zampini   PetscInt          i,j,k,total_counts,temp_start_ptr;
1691984c4197SStefano Zampini   /* stuff to store connected components stored in pcbddc->mat_graph */
1692984c4197SStefano Zampini   IS                ISForVertices,*ISForFaces,*ISForEdges,*used_IS;
1693984c4197SStefano Zampini   PetscInt          n_ISForFaces,n_ISForEdges;
1694984c4197SStefano Zampini   /* near null space stuff */
1695674ae819SStefano Zampini   MatNullSpace      nearnullsp;
1696674ae819SStefano Zampini   const Vec         *nearnullvecs;
1697674ae819SStefano Zampini   Vec               *localnearnullsp;
1698984c4197SStefano Zampini   PetscBool         nnsp_has_cnst;
1699984c4197SStefano Zampini   PetscInt          nnsp_size;
1700984c4197SStefano Zampini   PetscScalar       *array;
1701984c4197SStefano Zampini   /* BLAS integers */
1702e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
1703e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
1704c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
1705984c4197SStefano Zampini   /* LAPACK working arrays for SVD or POD */
1706242a89d7SStefano Zampini   PetscBool         skip_lapack;
1707984c4197SStefano Zampini   PetscScalar       *work;
1708984c4197SStefano Zampini   PetscReal         *singular_vals;
1709984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1710984c4197SStefano Zampini   PetscReal         *rwork;
1711674ae819SStefano Zampini #endif
1712984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1713e310c8b4SStefano Zampini   PetscBLASInt      Blas_one_2=1;
1714984c4197SStefano Zampini   PetscScalar       *temp_basis,*correlation_mat;
1715b7d8b9f8SStefano Zampini #else
1716b7d8b9f8SStefano Zampini   PetscBLASInt      dummy_int_1=1,dummy_int_2=1;
1717b7d8b9f8SStefano Zampini   PetscScalar       dummy_scalar_1=0.0,dummy_scalar_2=0.0;
1718984c4197SStefano Zampini #endif
1719727cdba6SStefano Zampini   /* reuse */
1720727cdba6SStefano Zampini   PetscInt          olocal_primal_size;
1721727cdba6SStefano Zampini   PetscInt          *oprimal_indices_local_idxs;
1722984c4197SStefano Zampini   /* change of basis */
1723984c4197SStefano Zampini   PetscInt          *aux_primal_numbering,*aux_primal_minloc,*global_indices;
1724a717540cSStefano Zampini   PetscBool         boolforchange,qr_needed;
1725a717540cSStefano Zampini   PetscBT           touched,change_basis,qr_needed_idx;
1726984c4197SStefano Zampini   /* auxiliary stuff */
172739e2fb2aSStefano Zampini   PetscInt          *nnz,*is_indices,*aux_primal_numbering_B;
1728*a58a30b4SStefano Zampini   PetscInt          ncc,*gidxs=NULL,*permutation=NULL,*temp_indices_to_constraint_work=NULL;
1729*a58a30b4SStefano Zampini   PetscScalar       *temp_quadrature_constraint_work=NULL;
1730984c4197SStefano Zampini   /* some quantities */
173145a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
1732*a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
1733984c4197SStefano Zampini 
1734674ae819SStefano Zampini 
1735674ae819SStefano Zampini   PetscFunctionBegin;
17368e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
17378e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
17388e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
173908122e43SStefano Zampini   /* TODO synch with adaptive selection */
1740674ae819SStefano Zampini   /* Get index sets for faces, edges and vertices from graph */
1741d06fc5fdSStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
1742d06fc5fdSStefano Zampini   /* free unneeded index sets */
1743d06fc5fdSStefano Zampini   if (!pcbddc->use_vertices) {
1744d06fc5fdSStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
1745674ae819SStefano Zampini   }
1746d06fc5fdSStefano Zampini   if (!pcbddc->use_edges) {
1747d06fc5fdSStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
1748d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1749d06fc5fdSStefano Zampini     }
1750d06fc5fdSStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1751d06fc5fdSStefano Zampini     n_ISForEdges = 0;
1752d06fc5fdSStefano Zampini   }
1753d06fc5fdSStefano Zampini   if (!pcbddc->use_faces) {
1754d06fc5fdSStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
1755d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1756d06fc5fdSStefano Zampini     }
1757d06fc5fdSStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1758d06fc5fdSStefano Zampini     n_ISForFaces = 0;
1759d06fc5fdSStefano Zampini   }
1760d06fc5fdSStefano Zampini   /* HACKS (the following two blocks of code) */
1761b9b85e73SStefano Zampini   if (!ISForVertices && pcbddc->NullSpace && !pcbddc->user_ChangeOfBasisMatrix) {
1762b8ffe317SStefano Zampini     pcbddc->use_change_of_basis = PETSC_TRUE;
1763d06fc5fdSStefano Zampini     if (!ISForEdges) {
1764d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = PETSC_TRUE;
1765d06fc5fdSStefano Zampini     }
1766b8ffe317SStefano Zampini   }
176798a51de6SStefano Zampini   if (pcbddc->NullSpace) {
176898a51de6SStefano Zampini     /* use_change_of_basis should be consistent among processors */
1769d06fc5fdSStefano Zampini     PetscBool tbool[2],gbool[2];
1770d06fc5fdSStefano Zampini     tbool [0] = pcbddc->use_change_of_basis;
1771d06fc5fdSStefano Zampini     tbool [1] = pcbddc->use_change_on_faces;
1772d06fc5fdSStefano Zampini     ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1773d06fc5fdSStefano Zampini     pcbddc->use_change_of_basis = gbool[0];
1774d06fc5fdSStefano Zampini     pcbddc->use_change_on_faces = gbool[1];
177598a51de6SStefano Zampini   }
1776984c4197SStefano Zampini   /* print some info */
1777674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
17780fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1779674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
1780674ae819SStefano Zampini     i = 0;
1781674ae819SStefano Zampini     if (ISForVertices) {
1782674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&i);CHKERRQ(ierr);
1783674ae819SStefano Zampini     }
1784674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices\n",PetscGlobalRank,i);CHKERRQ(ierr);
1785674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges\n",PetscGlobalRank,n_ISForEdges);CHKERRQ(ierr);
178615aaf578SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces\n",PetscGlobalRank,n_ISForFaces);CHKERRQ(ierr);
1787674ae819SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1788674ae819SStefano Zampini   }
178908122e43SStefano Zampini 
179008122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
1791674ae819SStefano Zampini     /* check if near null space is attached to global mat */
1792674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
1793674ae819SStefano Zampini     if (nearnullsp) {
1794674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1795f4ddd8eeSStefano Zampini       /* remove any stored info */
1796f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1797f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1798f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
1799f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
1800f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
1801473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1802f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
1803f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
1804f4ddd8eeSStefano Zampini       }
1805984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
1806984c4197SStefano Zampini       nnsp_size = 0;
1807674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
1808674ae819SStefano Zampini     }
1809984c4197SStefano Zampini     /* get max number of constraints on a single cc */
1810984c4197SStefano Zampini     max_constraints = nnsp_size;
1811984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
1812984c4197SStefano Zampini 
1813674ae819SStefano Zampini     /*
1814674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
1815674ae819SStefano Zampini          - temp_indices will contain start index of each constraint stored as follows
1816911cabfeSStefano 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
1817911cabfeSStefano 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
1818911cabfeSStefano Zampini          - temp_quadrature_constraint  [temp_indices[i],...,temp_indices[i+1]-1] will contain the scalars representing the constraint itself
1819674ae819SStefano Zampini                                                                                                                                                            */
1820674ae819SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
1821984c4197SStefano Zampini     total_counts *= max_constraints;
1822674ae819SStefano Zampini     n_vertices = 0;
1823674ae819SStefano Zampini     if (ISForVertices) {
1824674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
1825674ae819SStefano Zampini     }
1826674ae819SStefano Zampini     total_counts += n_vertices;
1827854ce69bSBarry Smith     ierr = PetscMalloc1(total_counts+1,&temp_indices);CHKERRQ(ierr);
18284641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
1829674ae819SStefano Zampini     total_counts = 0;
1830674ae819SStefano Zampini     max_size_of_constraint = 0;
1831674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
1832674ae819SStefano Zampini       if (i<n_ISForEdges) {
1833674ae819SStefano Zampini         used_IS = &ISForEdges[i];
1834674ae819SStefano Zampini       } else {
1835674ae819SStefano Zampini         used_IS = &ISForFaces[i-n_ISForEdges];
1836674ae819SStefano Zampini       }
1837674ae819SStefano Zampini       ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
1838674ae819SStefano Zampini       total_counts += j;
1839674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
1840674ae819SStefano Zampini     }
1841984c4197SStefano Zampini     total_counts *= max_constraints;
1842674ae819SStefano Zampini     total_counts += n_vertices;
1843906d46d4SStefano Zampini     ierr = PetscMalloc3(total_counts,&temp_quadrature_constraint,total_counts,&temp_indices_to_constraint,total_counts,&temp_indices_to_constraint_B);CHKERRQ(ierr);
1844984c4197SStefano Zampini     /* get local part of global near null space vectors */
1845785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
1846984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
1847984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
1848984c4197SStefano Zampini       ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1849984c4197SStefano Zampini       ierr = VecScatterEnd(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1850984c4197SStefano Zampini     }
1851674ae819SStefano Zampini 
1852242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
1853242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
1854a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
1855242a89d7SStefano Zampini 
18568f1c130eSStefano Zampini     /* allocate some auxiliary stuff */
18578f1c130eSStefano Zampini     if (!skip_lapack || pcbddc->use_qr_single) {
18588f1c130eSStefano 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);
18598f1c130eSStefano Zampini     }
18608f1c130eSStefano Zampini 
1861984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
1862a773dcb8SStefano Zampini     if (!skip_lapack) {
1863674ae819SStefano Zampini       PetscScalar temp_work;
1864911cabfeSStefano Zampini 
1865674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1866984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
1867785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
1868785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
1869785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
1870674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1871785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
1872674ae819SStefano Zampini #endif
1873674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
1874c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
1875c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
1876674ae819SStefano Zampini       lwork = -1;
1877674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1878674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1879c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
1880674ae819SStefano Zampini #else
1881c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
1882674ae819SStefano Zampini #endif
1883674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
1884984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
1885674ae819SStefano Zampini #else /* on missing GESVD */
1886674ae819SStefano Zampini       /* SVD */
1887674ae819SStefano Zampini       PetscInt max_n,min_n;
1888674ae819SStefano Zampini       max_n = max_size_of_constraint;
1889984c4197SStefano Zampini       min_n = max_constraints;
1890984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
1891674ae819SStefano Zampini         min_n = max_size_of_constraint;
1892984c4197SStefano Zampini         max_n = max_constraints;
1893674ae819SStefano Zampini       }
1894785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
1895674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1896785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
1897674ae819SStefano Zampini #endif
1898674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
1899674ae819SStefano Zampini       lwork = -1;
1900e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
1901e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
1902b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
1903674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1904674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1905e310c8b4SStefano 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));
1906674ae819SStefano Zampini #else
1907e310c8b4SStefano 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));
1908674ae819SStefano Zampini #endif
1909674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
1910984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
1911984c4197SStefano Zampini #endif /* on missing GESVD */
1912674ae819SStefano Zampini       /* Allocate optimal workspace */
1913674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
1914854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
1915674ae819SStefano Zampini     }
1916674ae819SStefano Zampini     /* Now we can loop on constraining sets */
1917674ae819SStefano Zampini     total_counts = 0;
1918674ae819SStefano Zampini     temp_indices[0] = 0;
1919674ae819SStefano Zampini     /* vertices */
1920674ae819SStefano Zampini     if (ISForVertices) {
1921674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1922674ae819SStefano Zampini       if (nnsp_has_cnst) { /* consider all vertices */
192339e2fb2aSStefano Zampini         ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
1924674ae819SStefano Zampini         for (i=0;i<n_vertices;i++) {
1925674ae819SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1926674ae819SStefano Zampini           temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1927674ae819SStefano Zampini           total_counts++;
1928674ae819SStefano Zampini         }
1929674ae819SStefano Zampini       } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
1930984c4197SStefano Zampini         PetscBool used_vertex;
1931674ae819SStefano Zampini         for (i=0;i<n_vertices;i++) {
1932674ae819SStefano Zampini           used_vertex = PETSC_FALSE;
1933674ae819SStefano Zampini           k = 0;
1934674ae819SStefano Zampini           while (!used_vertex && k<nnsp_size) {
1935984c4197SStefano Zampini             ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1936984c4197SStefano Zampini             if (PetscAbsScalar(array[is_indices[i]])>0.0) {
1937674ae819SStefano Zampini               temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1938674ae819SStefano Zampini               temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1939674ae819SStefano Zampini               temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1940674ae819SStefano Zampini               total_counts++;
1941674ae819SStefano Zampini               used_vertex = PETSC_TRUE;
1942674ae819SStefano Zampini             }
1943984c4197SStefano Zampini             ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1944674ae819SStefano Zampini             k++;
1945674ae819SStefano Zampini           }
1946674ae819SStefano Zampini         }
1947674ae819SStefano Zampini       }
1948674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1949674ae819SStefano Zampini       n_vertices = total_counts;
1950674ae819SStefano Zampini     }
1951984c4197SStefano Zampini 
1952674ae819SStefano Zampini     /* edges and faces */
1953911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
1954911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
1955911cabfeSStefano Zampini         used_IS = &ISForEdges[ncc];
1956984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
1957674ae819SStefano Zampini       } else {
1958911cabfeSStefano Zampini         used_IS = &ISForFaces[ncc-n_ISForEdges];
1959984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
1960674ae819SStefano Zampini       }
1961674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
1962674ae819SStefano Zampini       temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
1963674ae819SStefano Zampini       ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
1964674ae819SStefano Zampini       ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1965984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
1966984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
1967674ae819SStefano Zampini       if (nnsp_has_cnst) {
19685b08dc53SStefano Zampini         PetscScalar quad_value;
1969674ae819SStefano Zampini         temp_constraints++;
1970a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
1971674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
1972a773dcb8SStefano Zampini         } else {
1973a773dcb8SStefano Zampini           quad_value = 1.0;
1974a773dcb8SStefano Zampini         }
197539e2fb2aSStefano Zampini         ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1976674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
1977674ae819SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
1978674ae819SStefano Zampini         }
197908122e43SStefano Zampini         /* sort by global ordering if using lapack subroutines (not needed!) */
19808f1c130eSStefano Zampini         if (!skip_lapack || pcbddc->use_qr_single) {
1981911cabfeSStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
1982911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1983911cabfeSStefano Zampini             permutation[j]=j;
1984911cabfeSStefano Zampini           }
1985911cabfeSStefano Zampini           ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
1986911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
198708122e43SStefano Zampini             if (permutation[j]!=j) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"This should not happen");
198808122e43SStefano Zampini           }
198908122e43SStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1990911cabfeSStefano Zampini             temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
1991911cabfeSStefano Zampini             temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
1992911cabfeSStefano Zampini           }
1993911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1994911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
1995911cabfeSStefano Zampini         }
1996674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
1997674ae819SStefano Zampini         total_counts++;
1998674ae819SStefano Zampini       }
1999674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
2000984c4197SStefano Zampini         PetscReal real_value;
2001984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
200239e2fb2aSStefano Zampini         ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
2003674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
2004984c4197SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]+j]=array[is_indices[j]];
2005674ae819SStefano Zampini         }
2006984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2007984c4197SStefano Zampini         /* check if array is null on the connected component */
2008e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2009e310c8b4SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,&temp_quadrature_constraint[temp_indices[total_counts]],&Blas_one));
20105b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2011911cabfeSStefano Zampini           /* sort by global ordering if using lapack subroutines */
20128f1c130eSStefano Zampini           if (!skip_lapack || pcbddc->use_qr_single) {
2013911cabfeSStefano Zampini             ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
2014911cabfeSStefano Zampini             for (j=0;j<size_of_constraint;j++) {
2015911cabfeSStefano Zampini               permutation[j]=j;
2016911cabfeSStefano Zampini             }
2017911cabfeSStefano Zampini             ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
2018911cabfeSStefano Zampini             for (j=0;j<size_of_constraint;j++) {
2019911cabfeSStefano Zampini               temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
2020911cabfeSStefano Zampini               temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
2021911cabfeSStefano Zampini             }
2022911cabfeSStefano Zampini             ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
2023911cabfeSStefano Zampini             ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
2024911cabfeSStefano Zampini           }
2025674ae819SStefano Zampini           temp_constraints++;
2026674ae819SStefano Zampini           temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
2027674ae819SStefano Zampini           total_counts++;
2028674ae819SStefano Zampini         }
2029674ae819SStefano Zampini       }
2030674ae819SStefano Zampini       ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
203145a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2032eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2033a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
2034a773dcb8SStefano Zampini           PetscScalar norm;
2035a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2036a773dcb8SStefano 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));
2037a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
2038a773dcb8SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one));
2039a773dcb8SStefano Zampini         } else { /* perform SVD */
2040984c4197SStefano Zampini           PetscReal tol = 1.0e-8; /* tolerance for retaining eigenmodes */
2041674ae819SStefano Zampini 
2042674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2043984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
2044984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
2045984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
2046984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
2047984c4197SStefano Zampini                 from that computed using LAPACKgesvd
2048984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
2049984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
2050984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
2051674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
2052e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2053984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2054674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
2055674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
2056e310c8b4SStefano 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));
2057674ae819SStefano Zampini             }
2058674ae819SStefano Zampini           }
2059e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
2060e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2061e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
2062674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2063c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
2064674ae819SStefano Zampini #else
2065c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
2066674ae819SStefano Zampini #endif
2067674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2068984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
2069984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
2070674ae819SStefano Zampini           j = 0;
2071984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
2072674ae819SStefano Zampini           total_counts = total_counts-j;
207345a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
2074e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
2075c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2076c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2077c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
2078c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2079c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
2080c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2081674ae819SStefano Zampini           if (j<temp_constraints) {
2082984c4197SStefano Zampini             PetscInt ii;
2083984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]);
2084674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2085c4303822SStefano 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));
2086674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2087984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
2088674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
2089984c4197SStefano 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];
2090674ae819SStefano Zampini               }
2091674ae819SStefano Zampini             }
2092674ae819SStefano Zampini           }
2093674ae819SStefano Zampini #else  /* on missing GESVD */
2094e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2095e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2096b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2097674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2098674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2099e310c8b4SStefano 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));
2100674ae819SStefano Zampini #else
2101e310c8b4SStefano 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));
2102674ae819SStefano Zampini #endif
2103984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
2104674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2105984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
2106e310c8b4SStefano Zampini           k = temp_constraints;
2107e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
2108674ae819SStefano Zampini           j = 0;
2109e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
211045a1bb75SStefano Zampini           valid_constraints = k-j;
2111911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
2112984c4197SStefano Zampini #endif /* on missing GESVD */
2113674ae819SStefano Zampini         }
2114a773dcb8SStefano Zampini       }
211545a1bb75SStefano Zampini       /* setting change_of_basis flag is safe now */
211645a1bb75SStefano Zampini       if (boolforchange) {
211745a1bb75SStefano Zampini         for (j=0;j<valid_constraints;j++) {
211845a1bb75SStefano Zampini           PetscBTSet(change_basis,total_counts-j-1);
211945a1bb75SStefano Zampini         }
212045a1bb75SStefano Zampini       }
2121674ae819SStefano Zampini     }
2122984c4197SStefano Zampini     /* free workspace */
21238f1c130eSStefano Zampini     if (!skip_lapack || pcbddc->use_qr_single) {
2124911cabfeSStefano Zampini       ierr = PetscFree4(gidxs,permutation,temp_indices_to_constraint_work,temp_quadrature_constraint_work);CHKERRQ(ierr);
21258f1c130eSStefano Zampini     }
21268f1c130eSStefano Zampini     if (!skip_lapack) {
2127984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
2128984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2129984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
2130984c4197SStefano Zampini #endif
2131984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
2132984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2133984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
2134984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2135984c4197SStefano Zampini #endif
2136984c4197SStefano Zampini     }
2137984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2138984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
2139984c4197SStefano Zampini     }
2140984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
214108122e43SStefano Zampini   } else {
214208122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
214308122e43SStefano Zampini     PetscInt        cum = 0;
214408122e43SStefano Zampini 
214508122e43SStefano Zampini     total_counts = 0;
214608122e43SStefano Zampini     n_vertices = 0;
214708122e43SStefano Zampini     if (sub_schurs->is_Ej_com) {
214808122e43SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_Ej_com,&n_vertices);CHKERRQ(ierr);
214908122e43SStefano Zampini     }
215008122e43SStefano Zampini     max_constraints = 0;
215108122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
215208122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
215308122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
215408122e43SStefano Zampini     }
215508122e43SStefano Zampini     temp_indices = pcbddc->adaptive_constraints_ptrs;
215608122e43SStefano Zampini     temp_indices_to_constraint = pcbddc->adaptive_constraints_idxs;
215708122e43SStefano Zampini     temp_quadrature_constraint = pcbddc->adaptive_constraints_data;
215808122e43SStefano Zampini 
215908122e43SStefano Zampini #if 0
216008122e43SStefano Zampini     printf("Found %d totals\n",total_counts);
216108122e43SStefano Zampini     for (i=0;i<total_counts;i++) {
216208122e43SStefano Zampini       printf("const %d, start %d",i,temp_indices[i]);
216308122e43SStefano Zampini       printf(" end %d:\n",temp_indices[i+1]);
216408122e43SStefano Zampini       for (j=temp_indices[i];j<temp_indices[i+1];j++) {
216508122e43SStefano Zampini         printf("  idxs %d",temp_indices_to_constraint[j]);
216608122e43SStefano Zampini         printf("  data %1.2e\n",temp_quadrature_constraint[j]);
216708122e43SStefano Zampini       }
216808122e43SStefano Zampini     }
216908122e43SStefano Zampini #endif
217008122e43SStefano Zampini 
217108122e43SStefano Zampini     for (i=0;i<total_counts;i++) max_size_of_constraint = PetscMax(max_size_of_constraint,temp_indices[i+1]-temp_indices[i]);
217208122e43SStefano Zampini     ierr = PetscMalloc1(temp_indices[total_counts],&temp_indices_to_constraint_B);CHKERRQ(ierr);
217308122e43SStefano Zampini     /* Change of basis */
217408122e43SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
217508122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
2176bbb9e6c6SStefano Zampini       cum = n_vertices;
217708122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
217808122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
2179bbb9e6c6SStefano Zampini           for (j=0;j<pcbddc->adaptive_constraints_n[i+n_vertices];j++) {
218008122e43SStefano Zampini             ierr = PetscBTSet(change_basis,cum+j);CHKERRQ(ierr);
218108122e43SStefano Zampini           }
218208122e43SStefano Zampini         }
2183bbb9e6c6SStefano Zampini         cum += pcbddc->adaptive_constraints_n[i+n_vertices];
218408122e43SStefano Zampini       }
218508122e43SStefano Zampini     }
218608122e43SStefano Zampini   }
218708122e43SStefano Zampini 
218808122e43SStefano Zampini   /* free index sets of faces, edges and vertices */
218908122e43SStefano Zampini   for (i=0;i<n_ISForFaces;i++) {
219008122e43SStefano Zampini     ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
219108122e43SStefano Zampini   }
219208122e43SStefano Zampini   if (n_ISForFaces) {
219308122e43SStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
219408122e43SStefano Zampini   }
219508122e43SStefano Zampini   for (i=0;i<n_ISForEdges;i++) {
219608122e43SStefano Zampini     ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
219708122e43SStefano Zampini   }
219808122e43SStefano Zampini   if (n_ISForEdges) {
219908122e43SStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
220008122e43SStefano Zampini   }
220108122e43SStefano Zampini   ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
220208122e43SStefano Zampini 
220308122e43SStefano Zampini   /* map temp_indices_to_constraint in boundary numbering */
220408122e43SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,temp_indices[total_counts],temp_indices_to_constraint,&i,temp_indices_to_constraint_B);CHKERRQ(ierr);
220508122e43SStefano Zampini   if (i != temp_indices[total_counts]) {
220608122e43SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",temp_indices[total_counts],i);
220708122e43SStefano Zampini   }
2208984c4197SStefano Zampini 
2209727cdba6SStefano Zampini   /* set quantities in pcbddc data structure and store previous primal size */
2210984c4197SStefano Zampini   /* n_vertices defines the number of subdomain corners in the primal space */
2211674ae819SStefano Zampini   /* n_constraints defines the number of averages (they can be point primal dofs if change of basis is requested) */
2212727cdba6SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
2213984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
2214674ae819SStefano Zampini   pcbddc->n_vertices = n_vertices;
2215984c4197SStefano Zampini   pcbddc->n_constraints = pcbddc->local_primal_size-pcbddc->n_vertices;
2216674ae819SStefano Zampini 
2217674ae819SStefano Zampini   /* Create constraint matrix */
2218674ae819SStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
2219674ae819SStefano Zampini   /* so we need to set it up properly either with or without change of basis */
2220674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2221674ae819SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
2222984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
2223984c4197SStefano Zampini   /* array to compute a local numbering of constraints : vertices first then constraints */
2224785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_numbering);CHKERRQ(ierr);
2225984c4197SStefano Zampini   /* array to select the proper local node (of minimum index with respect to global ordering) when changing the basis */
2226984c4197SStefano 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 */
2227785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_minloc);CHKERRQ(ierr);
2228984c4197SStefano Zampini   /* auxiliary stuff for basis change */
2229785e854fSJed Brown   ierr = PetscMalloc1(max_size_of_constraint,&global_indices);CHKERRQ(ierr);
22304641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n_B,&touched);CHKERRQ(ierr);
2231984c4197SStefano Zampini 
2232984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
2233984c4197SStefano Zampini   total_primal_vertices=0;
2234984c4197SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
2235674ae819SStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
2236984c4197SStefano Zampini     if (size_of_constraint == 1) {
22374641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]]);CHKERRQ(ierr);
2238984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]];
2239984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=0;
2240984c4197SStefano Zampini       total_primal_vertices++;
22414641a718SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) { /* Same procedure used in PCBDDCGetPrimalConstraintsLocalIdx */
2242984c4197SStefano Zampini       PetscInt min_loc,min_index;
2243984c4197SStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],global_indices);CHKERRQ(ierr);
2244984c4197SStefano Zampini       /* find first untouched local node */
2245674ae819SStefano Zampini       k = 0;
22464641a718SStefano Zampini       while (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) k++;
2247984c4197SStefano Zampini       min_index = global_indices[k];
2248984c4197SStefano Zampini       min_loc = k;
2249984c4197SStefano Zampini       /* search the minimum among global nodes already untouched on the cc */
2250984c4197SStefano Zampini       for (k=1;k<size_of_constraint;k++) {
2251984c4197SStefano Zampini         /* there can be more than one constraint on a single connected component */
22524641a718SStefano Zampini         if (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k]) && min_index > global_indices[k]) {
2253984c4197SStefano Zampini           min_index = global_indices[k];
2254984c4197SStefano Zampini           min_loc = k;
2255674ae819SStefano Zampini         }
2256674ae819SStefano Zampini       }
22574641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]+min_loc]);CHKERRQ(ierr);
2258984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]+min_loc];
2259984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=min_loc;
2260984c4197SStefano Zampini       total_primal_vertices++;
2261984c4197SStefano Zampini     }
2262984c4197SStefano Zampini   }
2263a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
2264a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
2265a717540cSStefano Zampini   ierr = PetscBTCreate(pcbddc->local_primal_size,&qr_needed_idx);CHKERRQ(ierr);
2266a717540cSStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2267a717540cSStefano Zampini     if (PetscBTLookup(change_basis,i)) {
2268fa434743SStefano Zampini       if (!pcbddc->use_qr_single) {
2269a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2270a717540cSStefano Zampini         j = 0;
2271a717540cSStefano Zampini         for (k=0;k<size_of_constraint;k++) {
2272a717540cSStefano Zampini           if (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) {
2273a717540cSStefano Zampini             j++;
2274a717540cSStefano Zampini           }
2275a717540cSStefano Zampini         }
2276a717540cSStefano Zampini         /* found more than one primal dof on the cc */
2277a717540cSStefano Zampini         if (j > 1) {
2278a717540cSStefano Zampini           PetscBTSet(qr_needed_idx,i);
2279a717540cSStefano Zampini           qr_needed = PETSC_TRUE;
2280a717540cSStefano Zampini         }
2281fa434743SStefano Zampini       } else {
2282fa434743SStefano Zampini         PetscBTSet(qr_needed_idx,i);
2283fa434743SStefano Zampini         qr_needed = PETSC_TRUE;
2284fa434743SStefano Zampini       }
2285a717540cSStefano Zampini     }
2286a717540cSStefano Zampini   }
2287984c4197SStefano Zampini   /* free workspace */
2288984c4197SStefano Zampini   ierr = PetscFree(global_indices);CHKERRQ(ierr);
228945a1bb75SStefano Zampini 
2290674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
2291a717540cSStefano Zampini   ierr = PetscSortInt(total_primal_vertices,aux_primal_numbering);CHKERRQ(ierr);
2292984c4197SStefano Zampini 
2293984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
2294785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2295984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i]=1;
2296984c4197SStefano Zampini   j=total_primal_vertices;
2297984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
22984641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2299674ae819SStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
2300674ae819SStefano Zampini       j++;
2301674ae819SStefano Zampini     }
2302674ae819SStefano Zampini   }
2303674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2304674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2305674ae819SStefano Zampini   /* set values in constraint matrix */
2306984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
2307984c4197SStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,aux_primal_numbering[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2308674ae819SStefano Zampini   }
2309984c4197SStefano Zampini   total_counts = total_primal_vertices;
2310984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
23114641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2312674ae819SStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
2313674ae819SStefano 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);
2314674ae819SStefano Zampini       total_counts++;
2315674ae819SStefano Zampini     }
2316674ae819SStefano Zampini   }
2317674ae819SStefano Zampini   /* assembling */
2318674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2319674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2320984c4197SStefano Zampini   /*
232145a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2322984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2323984c4197SStefano Zampini   */
2324674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2325674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2326026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2327984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2328026de310SStefano Zampini     /* iterator on aux_primal_minloc (ordered as read from nearnullspace: vertices, edges and then constraints) */
2329026de310SStefano Zampini     PetscInt     primal_counter;
2330984c4197SStefano Zampini     /* working stuff for GEQRF */
233181d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2332984c4197SStefano Zampini     PetscBLASInt lqr_work;
2333984c4197SStefano Zampini     /* working stuff for UNGQR */
2334984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2335984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2336984c4197SStefano Zampini     /* working stuff for TRTRS */
2337984c4197SStefano Zampini     PetscScalar  *trs_rhs;
23383f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2339984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2340984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2341984c4197SStefano Zampini     PetscScalar  *start_vals;
2342984c4197SStefano Zampini     /* working stuff for values insertion */
23434641a718SStefano Zampini     PetscBT      is_primal;
2344906d46d4SStefano Zampini     /* matrix sizes */
2345906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2346906d46d4SStefano Zampini     /* temporary change of basis */
2347906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2348984c4197SStefano Zampini 
2349906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2350906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
2351906d46d4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
2352bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
2353906d46d4SStefano Zampini 
2354906d46d4SStefano Zampini     /* nonzeros for local mat */
2355bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
2356bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
2357a717540cSStefano Zampini     for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2358a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
2359a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2360a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
2361bbb9e6c6SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint[temp_indices[i]+j]] = size_of_constraint;
2362a717540cSStefano Zampini         } else {
2363bbb9e6c6SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint[temp_indices[i]+j]] = 2;
2364a717540cSStefano Zampini           /* get local primal index on the cc */
2365a717540cSStefano Zampini           j = 0;
2366a717540cSStefano Zampini           while (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+j])) j++;
2367bbb9e6c6SStefano Zampini           nnz[temp_indices_to_constraint[temp_indices[i]+j]] = size_of_constraint;
2368a717540cSStefano Zampini         }
2369a717540cSStefano Zampini       }
2370a717540cSStefano Zampini     }
2371906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2372bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2373a717540cSStefano Zampini     /* Set initial identity in the matrix */
2374bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
2375906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2376a717540cSStefano Zampini     }
2377a717540cSStefano Zampini 
2378a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2379a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2380a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2381a717540cSStefano Zampini     }
2382a717540cSStefano Zampini 
2383a717540cSStefano Zampini 
2384a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2385a717540cSStefano Zampini     /*
2386a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2387a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2388a717540cSStefano Zampini 
2389a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2390a717540cSStefano Zampini 
2391a6b551f4SStefano 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)
2392a6b551f4SStefano Zampini 
2393a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2394a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2395a717540cSStefano Zampini             |              ...                        |
2396a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2397a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2398a717540cSStefano Zampini 
2399a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2400a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2401a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2402a6b551f4SStefano Zampini 
2403a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2404a717540cSStefano Zampini     */
2405a717540cSStefano Zampini     if (qr_needed) {
2406984c4197SStefano Zampini       /* space to store Q */
2407854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2408984c4197SStefano Zampini       /* first we issue queries for optimal work */
24093f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
24103f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
24113f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2412984c4197SStefano Zampini       lqr_work = -1;
24133f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2414984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
2415984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
2416785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
2417984c4197SStefano Zampini       lgqr_work = -1;
24183f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
24193f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
24203f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
24213f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
24223f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
24233f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
2424984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
2425984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
2426785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
2427984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
2428785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
2429984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
2430785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
2431a717540cSStefano Zampini       /* allocating workspace for check */
2432a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
2433785e854fSJed Brown         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&work);CHKERRQ(ierr);
2434a717540cSStefano Zampini       }
2435a717540cSStefano Zampini     }
2436984c4197SStefano Zampini     /* array to store whether a node is primal or not */
24374641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
2438473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
24395e8657edSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,aux_primal_numbering,&i,aux_primal_numbering_B);CHKERRQ(ierr);
244039e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
244139e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
24424641a718SStefano Zampini     }
244339e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
244439e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
244539e2fb2aSStefano Zampini     }
244639e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
2447984c4197SStefano Zampini 
2448a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
2449026de310SStefano Zampini     /* -> using implicit ordering contained in temp_indices data */
2450026de310SStefano Zampini     total_counts = pcbddc->n_vertices;
2451026de310SStefano Zampini     primal_counter = total_counts;
2452026de310SStefano Zampini     while (total_counts<pcbddc->local_primal_size) {
2453026de310SStefano Zampini       primal_dofs = 1;
24544641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
2455026de310SStefano Zampini         /* get all constraints with same support: if more then one constraint is present on the cc then surely indices are stored contiguosly */
2456bbb9e6c6SStefano Zampini         while (total_counts+primal_dofs < pcbddc->local_primal_size && temp_indices_to_constraint[temp_indices[total_counts]] == temp_indices_to_constraint[temp_indices[total_counts+primal_dofs]]) {
2457026de310SStefano Zampini           primal_dofs++;
2458674ae819SStefano Zampini         }
2459984c4197SStefano Zampini         /* get constraint info */
2460026de310SStefano Zampini         size_of_constraint = temp_indices[total_counts+1]-temp_indices[total_counts];
2461984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
2462984c4197SStefano Zampini 
2463984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2464a717540cSStefano 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);
2465674ae819SStefano Zampini         }
2466984c4197SStefano Zampini 
2467fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
2468a717540cSStefano Zampini 
2469a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
2470a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
2471a717540cSStefano Zampini             ierr = PetscMemcpy(work,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2472a717540cSStefano Zampini           }
2473984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
2474026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2475984c4197SStefano Zampini 
2476984c4197SStefano Zampini           /* compute QR decomposition of constraints */
24773f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
24783f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
24793f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2480674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
24813f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
2482984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
2483674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2484984c4197SStefano Zampini 
2485984c4197SStefano Zampini           /* explictly compute R^-T */
2486984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
2487984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
24883f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
24893f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
24903f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
24913f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
2492984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
24933f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
2494984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
2495984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2496984c4197SStefano Zampini 
2497a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
24983f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
24993f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
25003f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
25013f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2502984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
25033f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
2504984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
2505984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2506984c4197SStefano Zampini 
2507984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
2508984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
2509984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
25103f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
25113f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
25123f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
25133f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
25143f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
25153f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2516984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2517c4303822SStefano 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));
2518984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2519026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2520984c4197SStefano Zampini 
2521984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
2522bbb9e6c6SStefano Zampini           start_rows = &temp_indices_to_constraint[temp_indices[total_counts]];
2523984c4197SStefano Zampini           /* insert cols for primal dofs */
2524984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
2525984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
2526bbb9e6c6SStefano Zampini             start_cols = &temp_indices_to_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter+j]];
2527906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2528984c4197SStefano Zampini           }
2529984c4197SStefano Zampini           /* insert cols for dual dofs */
2530984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
25314641a718SStefano Zampini             if (!PetscBTLookup(is_primal,temp_indices_to_constraint_B[temp_indices[total_counts]+k])) {
2532984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
2533bbb9e6c6SStefano Zampini               start_cols = &temp_indices_to_constraint[temp_indices[total_counts]+k];
2534906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2535984c4197SStefano Zampini               j++;
2536674ae819SStefano Zampini             }
2537674ae819SStefano Zampini           }
2538984c4197SStefano Zampini 
2539984c4197SStefano Zampini           /* check change of basis */
2540984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
2541984c4197SStefano Zampini             PetscInt   ii,jj;
2542984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
2543c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
2544c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2545c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
2546c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2547c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
2548c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
2549984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2550c4303822SStefano 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));
2551984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2552984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
2553984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
2554984c4197SStefano Zampini                 if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
2555984c4197SStefano Zampini                 if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
2556674ae819SStefano Zampini               }
2557674ae819SStefano Zampini             }
2558984c4197SStefano Zampini             if (!valid_qr) {
255922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
2560984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
2561984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
2562984c4197SStefano Zampini                   if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
2563984c4197SStefano 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]));
2564674ae819SStefano Zampini                   }
2565984c4197SStefano Zampini                   if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
2566984c4197SStefano 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]));
2567984c4197SStefano Zampini                   }
2568984c4197SStefano Zampini                 }
2569984c4197SStefano Zampini               }
2570674ae819SStefano Zampini             } else {
257122d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
2572674ae819SStefano Zampini             }
2573674ae819SStefano Zampini           }
2574a717540cSStefano Zampini         } else { /* simple transformation block */
2575a717540cSStefano Zampini           PetscInt    row,col;
2576a6b551f4SStefano Zampini           PetscScalar val,norm;
2577a6b551f4SStefano Zampini 
2578a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2579a6b551f4SStefano 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));
2580a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
2581bbb9e6c6SStefano Zampini             PetscInt row_B = temp_indices_to_constraint_B[temp_indices[total_counts]+j];
2582bbb9e6c6SStefano Zampini             row = temp_indices_to_constraint[temp_indices[total_counts]+j];
2583bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
2584bbb9e6c6SStefano Zampini               col = temp_indices_to_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2585906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
2586a6b551f4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,temp_quadrature_constraint[temp_indices[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
2587a717540cSStefano Zampini             } else {
2588a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
2589bbb9e6c6SStefano Zampini                 col = temp_indices_to_constraint[temp_indices[total_counts]+k];
2590a717540cSStefano Zampini                 if (row != col) {
2591a717540cSStefano Zampini                   val = -temp_quadrature_constraint[temp_indices[total_counts]+k]/temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2592a717540cSStefano Zampini                 } else {
2593a6b551f4SStefano Zampini                   val = temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]]/norm;
2594a717540cSStefano Zampini                 }
2595906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
2596a717540cSStefano Zampini               }
2597a717540cSStefano Zampini             }
2598a717540cSStefano Zampini           }
259998a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
260022d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
2601a717540cSStefano Zampini           }
2602674ae819SStefano Zampini         }
2603026de310SStefano Zampini         /* increment primal counter */
2604026de310SStefano Zampini         primal_counter += primal_dofs;
2605984c4197SStefano Zampini       } else {
2606984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2607026de310SStefano 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);
2608674ae819SStefano Zampini         }
2609674ae819SStefano Zampini       }
2610026de310SStefano Zampini       /* increment constraint counter total_counts */
2611026de310SStefano Zampini       total_counts += primal_dofs;
2612674ae819SStefano Zampini     }
2613a717540cSStefano Zampini 
2614a717540cSStefano Zampini     /* free workspace */
2615a717540cSStefano Zampini     if (qr_needed) {
2616984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
2617984c4197SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
2618984c4197SStefano Zampini       }
2619984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
2620984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
2621984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
2622984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
2623984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
2624674ae819SStefano Zampini     }
2625a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
2626906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2627906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2628906d46d4SStefano Zampini 
2629906d46d4SStefano Zampini     /* assembling of global change of variable */
2630bbb9e6c6SStefano Zampini     {
2631bbb9e6c6SStefano Zampini       Mat tmat;
2632906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2633906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2634bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
2635bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
2636bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2637bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2638906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2639bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
2640bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2641bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2642bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2643bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
2644bbb9e6c6SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2645bbb9e6c6SStefano Zampini       ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2646bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
2647bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
2648906d46d4SStefano Zampini     }
2649906d46d4SStefano Zampini     /* check */
2650906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
2651906d46d4SStefano Zampini       PetscReal error;
2652906d46d4SStefano Zampini       Vec       x,x_change;
2653906d46d4SStefano Zampini 
2654906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
2655906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
2656906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2657906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
2658bbb9e6c6SStefano Zampini       ierr = VecScatterBegin(matis->ctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2659bbb9e6c6SStefano Zampini       ierr = VecScatterEnd(matis->ctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2660bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2661bbb9e6c6SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2662bbb9e6c6SStefano Zampini       ierr = VecScatterEnd(matis->ctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2663906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
2664906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2665906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2666906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2667bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
2668906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
2669906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2670906d46d4SStefano Zampini     }
2671b96c3477SStefano Zampini 
2672b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
2673b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
2674b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
2675b96c3477SStefano Zampini       if (sub_schurs->n_subs_par_g) {
2676b7eb3628SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Change of basis with deluxe scaling and parallel problems still needs to be implemented");
2677b96c3477SStefano Zampini       }
2678b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
2679b96c3477SStefano Zampini         Mat S_1,S_2,tmat;
2680bbb9e6c6SStefano Zampini         IS is_all_N;
2681bbb9e6c6SStefano Zampini 
2682bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
2683bbb9e6c6SStefano Zampini         ierr = MatGetSubMatrixUnsorted(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
2684bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
2685b96c3477SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_1);CHKERRQ(ierr);
2686b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
2687b96c3477SStefano Zampini         sub_schurs->S_Ej_all = S_1;
2688b96c3477SStefano Zampini         ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_2);CHKERRQ(ierr);
2689b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
2690b96c3477SStefano Zampini         sub_schurs->sum_S_Ej_all = S_2;
2691b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2692b96c3477SStefano Zampini       }
2693b96c3477SStefano Zampini     }
2694906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
2695906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
2696b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2697b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
2698b9b85e73SStefano Zampini   }
2699906d46d4SStefano Zampini 
2700906d46d4SStefano Zampini   /* set up change of basis context */
2701906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2702906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
2703906d46d4SStefano Zampini 
2704906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
2705906d46d4SStefano Zampini       PetscInt global_size,local_size;
2706906d46d4SStefano Zampini 
2707906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2708906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2709906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
2710906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2711906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
2712906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
2713906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
2714906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
2715906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
2716906d46d4SStefano Zampini     } else {
2717906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
2718906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
2719906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
2720906d46d4SStefano Zampini     }
2721906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
2722906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2723906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
2724906d46d4SStefano Zampini     } else {
2725906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2726906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
2727906d46d4SStefano Zampini     }
2728906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
2729906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
2730906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2731906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2732b9b85e73SStefano Zampini   }
2733a717540cSStefano Zampini 
2734727cdba6SStefano Zampini   /* get indices in local ordering for vertices and constraints */
2735727cdba6SStefano 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 */
2736473ba861SJed Brown     ierr = PetscMalloc1(olocal_primal_size,&oprimal_indices_local_idxs);CHKERRQ(ierr);
2737727cdba6SStefano Zampini     ierr = PetscMemcpy(oprimal_indices_local_idxs,pcbddc->primal_indices_local_idxs,olocal_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2738727cdba6SStefano Zampini   }
2739727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2740f347579bSStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2741473ba861SJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2742727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_primal_numbering);CHKERRQ(ierr);
2743727cdba6SStefano Zampini   ierr = PetscMemcpy(pcbddc->primal_indices_local_idxs,aux_primal_numbering,i*sizeof(PetscInt));CHKERRQ(ierr);
2744727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2745727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_primal_numbering);CHKERRQ(ierr);
2746727cdba6SStefano Zampini   ierr = PetscMemcpy(&pcbddc->primal_indices_local_idxs[i],aux_primal_numbering,j*sizeof(PetscInt));CHKERRQ(ierr);
2747727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2748e9189074SStefano Zampini   /* set quantities in PCBDDC data struct */
2749e9189074SStefano Zampini   pcbddc->n_actual_vertices = i;
2750727cdba6SStefano Zampini   /* check if a new primal space has been introduced */
2751727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
2752727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
2753727cdba6SStefano Zampini     ierr = PetscMemcmp(pcbddc->primal_indices_local_idxs,oprimal_indices_local_idxs,olocal_primal_size,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
2754c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
2755727cdba6SStefano Zampini     ierr = PetscFree(oprimal_indices_local_idxs);CHKERRQ(ierr);
2756727cdba6SStefano Zampini   }
2757727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
2758727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2759727cdba6SStefano Zampini 
2760a717540cSStefano Zampini   /* flush dbg viewer */
2761b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
2762b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2763b8ffe317SStefano Zampini   }
2764a717540cSStefano Zampini 
2765e310c8b4SStefano Zampini   /* free workspace */
2766a717540cSStefano Zampini   ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2767a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
2768984c4197SStefano Zampini   ierr = PetscFree(aux_primal_minloc);CHKERRQ(ierr);
27694641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
277008122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
2771906d46d4SStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
2772906d46d4SStefano Zampini     ierr = PetscFree3(temp_quadrature_constraint,temp_indices_to_constraint,temp_indices_to_constraint_B);CHKERRQ(ierr);
277308122e43SStefano Zampini   } else {
277408122e43SStefano Zampini     ierr = PetscFree4(pcbddc->adaptive_constraints_n,
277508122e43SStefano Zampini                       pcbddc->adaptive_constraints_ptrs,
277608122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
277708122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
277808122e43SStefano Zampini     ierr = PetscFree(temp_indices_to_constraint_B);CHKERRQ(ierr);
277908122e43SStefano Zampini   }
2780674ae819SStefano Zampini   PetscFunctionReturn(0);
2781674ae819SStefano Zampini }
2782674ae819SStefano Zampini 
2783674ae819SStefano Zampini #undef __FUNCT__
2784674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
2785674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
2786674ae819SStefano Zampini {
2787674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
2788674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
2789674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
279063602bcaSStefano Zampini   PetscInt    ierr,i,vertex_size;
2791674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
2792674ae819SStefano Zampini 
2793674ae819SStefano Zampini   PetscFunctionBegin;
27948e61c736SStefano Zampini   /* Reset previously computed graph */
27958e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
2796674ae819SStefano Zampini   /* Init local Graph struct */
2797674ae819SStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,matis->mapping);CHKERRQ(ierr);
2798674ae819SStefano Zampini 
2799575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
2800575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
2801575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2802575ad6abSStefano Zampini   }
28039577ea80SStefano Zampini 
2804674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
28054d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
2806674ae819SStefano Zampini     Mat       mat_adj;
28074d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
28084d379d7bSStefano Zampini     PetscInt  nvtxs;
2809674ae819SStefano Zampini     PetscBool flg_row=PETSC_TRUE;
2810674ae819SStefano Zampini 
2811674ae819SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
28124d379d7bSStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2813674ae819SStefano Zampini     if (!flg_row) {
2814674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2815674ae819SStefano Zampini     }
28164d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
28174d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
2818b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
28194d379d7bSStefano Zampini     } else { /* just compute subdomain's connected components */
28204d379d7bSStefano Zampini       IS                     is_dummy;
28214d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
28224d379d7bSStefano Zampini       PetscInt               j,sum;
28234d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
28244d379d7bSStefano Zampini       const PetscInt         *idxs;
28254d379d7bSStefano Zampini       PCBDDCGraph            graph;
28264d379d7bSStefano Zampini       PetscBT                is_on_boundary;
28274d379d7bSStefano Zampini 
28284d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
28294d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
28304d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
28314d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
28324d379d7bSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy);CHKERRQ(ierr);
28334d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
28344d379d7bSStefano Zampini       graph->xadj = xadj;
28354d379d7bSStefano Zampini       graph->adjncy = adjncy;
28364d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
28374d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
28384d379d7bSStefano Zampini 
28394d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
28404d379d7bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains\n",PetscGlobalRank,graph->ncc);CHKERRQ(ierr);
28414d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
28424d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
28434d379d7bSStefano Zampini         }
28444d379d7bSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
28454d379d7bSStefano Zampini       }
28464d379d7bSStefano Zampini 
28474d379d7bSStefano Zampini       ierr = PetscBTCreate(nvtxs,&is_on_boundary);CHKERRQ(ierr);
28484d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
28494d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
28504d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
28514d379d7bSStefano Zampini       }
28524d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
28534d379d7bSStefano Zampini 
28544d379d7bSStefano Zampini       ierr = PetscCalloc1(nvtxs+1,&cxadj);CHKERRQ(ierr);
28554d379d7bSStefano Zampini       sum = 0;
28564d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
28574d379d7bSStefano Zampini         PetscInt sizecc = 0;
28584d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
28594d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
28604d379d7bSStefano Zampini             sizecc++;
28614d379d7bSStefano Zampini           }
28624d379d7bSStefano Zampini         }
28634d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
28644d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
28654d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
28664d379d7bSStefano Zampini           }
28674d379d7bSStefano Zampini         }
28684d379d7bSStefano Zampini         sum += sizecc*sizecc;
28694d379d7bSStefano Zampini       }
28704d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
28714d379d7bSStefano Zampini       sum = 0;
28724d379d7bSStefano Zampini       for (i=0;i<nvtxs;i++) {
28734d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
28744d379d7bSStefano Zampini         cxadj[i] = sum;
28754d379d7bSStefano Zampini         sum += temp;
28764d379d7bSStefano Zampini       }
28774d379d7bSStefano Zampini       cxadj[nvtxs] = sum;
28784d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
28794d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
28804d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
28814d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
28824d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
28834d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
28844d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
28854d379d7bSStefano Zampini                 sizecc++;
28864d379d7bSStefano Zampini               }
28874d379d7bSStefano Zampini             }
28884d379d7bSStefano Zampini           }
28894d379d7bSStefano Zampini         }
28904d379d7bSStefano Zampini       }
28914d379d7bSStefano Zampini       if (nvtxs) {
28924d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
28934d379d7bSStefano Zampini       } else {
28944d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
28954d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
28964d379d7bSStefano Zampini       }
28974d379d7bSStefano Zampini       graph->xadj = 0;
28984d379d7bSStefano Zampini       graph->adjncy = 0;
28994d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
29004d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
29014d379d7bSStefano Zampini     }
29024d379d7bSStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2903674ae819SStefano Zampini     if (!flg_row) {
2904674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2905674ae819SStefano Zampini     }
2906674ae819SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2907674ae819SStefano Zampini   }
2908674ae819SStefano Zampini 
290963602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
2910674ae819SStefano Zampini   vertex_size = 1;
291163602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
291263602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
291395ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
291463602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
2915a7dc3881SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
291663602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2917674ae819SStefano Zampini       }
291863602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
291963602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
292063602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
2921674ae819SStefano Zampini     }
292263602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
2923674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
292463602bcaSStefano Zampini   } else {
292563602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
292663602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
2927854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
292863602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
292963602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
293063602bcaSStefano Zampini       }
293163602bcaSStefano Zampini     }
2932674ae819SStefano Zampini   }
2933674ae819SStefano Zampini 
2934674ae819SStefano Zampini   /* Setup of Graph */
2935785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
2936a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
2937785d1243SStefano Zampini   }
2938785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
2939a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2940785d1243SStefano Zampini   }
294163602bcaSStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);
2942674ae819SStefano Zampini 
2943674ae819SStefano Zampini   /* Graph's connected components analysis */
2944674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
2945674ae819SStefano Zampini 
2946674ae819SStefano Zampini   /* print some info to stdout */
2947674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
2948e49050b4SStefano Zampini     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);
2949674ae819SStefano Zampini   }
2950fb180af4SStefano Zampini 
2951fb180af4SStefano Zampini   /* mark topography has done */
2952fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
2953674ae819SStefano Zampini   PetscFunctionReturn(0);
2954674ae819SStefano Zampini }
2955674ae819SStefano Zampini 
2956674ae819SStefano Zampini #undef __FUNCT__
2957674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalVerticesLocalIdx"
2958f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalVerticesLocalIdx(PC pc, PetscInt *n_vertices, PetscInt **vertices_idx)
2959674ae819SStefano Zampini {
2960674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2961674ae819SStefano Zampini   PetscInt       *vertices,*row_cmat_indices,n,i,size_of_constraint,local_primal_size;
2962674ae819SStefano Zampini   PetscErrorCode ierr;
2963674ae819SStefano Zampini 
2964674ae819SStefano Zampini   PetscFunctionBegin;
2965674ae819SStefano Zampini   n = 0;
2966674ae819SStefano Zampini   vertices = 0;
2967674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
2968674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&i);CHKERRQ(ierr);
2969b120a5c6SStefano Zampini     for (i=0;i<local_primal_size;i++) {
2970b120a5c6SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2971b120a5c6SStefano Zampini       if (size_of_constraint == 1) n++;
2972b120a5c6SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2973b120a5c6SStefano Zampini     }
2974811e8ca2SStefano Zampini     if (vertices_idx) {
2975785e854fSJed Brown       ierr = PetscMalloc1(n,&vertices);CHKERRQ(ierr);
2976b120a5c6SStefano Zampini       n = 0;
2977674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
2978674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2979674ae819SStefano Zampini         if (size_of_constraint == 1) {
2980674ae819SStefano Zampini           vertices[n++]=row_cmat_indices[0];
2981674ae819SStefano Zampini         }
2982674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2983674ae819SStefano Zampini       }
2984674ae819SStefano Zampini     }
2985811e8ca2SStefano Zampini   }
2986674ae819SStefano Zampini   *n_vertices = n;
2987811e8ca2SStefano Zampini   if (vertices_idx) *vertices_idx = vertices;
2988674ae819SStefano Zampini   PetscFunctionReturn(0);
2989674ae819SStefano Zampini }
2990674ae819SStefano Zampini 
2991674ae819SStefano Zampini #undef __FUNCT__
2992674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalConstraintsLocalIdx"
2993f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalConstraintsLocalIdx(PC pc, PetscInt *n_constraints, PetscInt **constraints_idx)
2994674ae819SStefano Zampini {
2995674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2996674ae819SStefano Zampini   PetscInt       *constraints_index,*row_cmat_indices,*row_cmat_global_indices;
2997674ae819SStefano Zampini   PetscInt       n,i,j,size_of_constraint,local_primal_size,local_size,max_size_of_constraint,min_index,min_loc;
29984641a718SStefano Zampini   PetscBT        touched;
2999674ae819SStefano Zampini   PetscErrorCode ierr;
3000674ae819SStefano Zampini 
3001f34684f1SStefano Zampini     /* This function assumes that the number of local constraints per connected component
3002f34684f1SStefano Zampini        is not greater than the number of nodes defined for the connected component
3003f34684f1SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
3004674ae819SStefano Zampini   PetscFunctionBegin;
3005674ae819SStefano Zampini   n = 0;
3006674ae819SStefano Zampini   constraints_index = 0;
3007674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
3008674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&local_size);CHKERRQ(ierr);
3009674ae819SStefano Zampini     max_size_of_constraint = 0;
3010674ae819SStefano Zampini     for (i=0;i<local_primal_size;i++) {
3011674ae819SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
3012674ae819SStefano Zampini       if (size_of_constraint > 1) {
3013674ae819SStefano Zampini         n++;
3014674ae819SStefano Zampini       }
3015674ae819SStefano Zampini       max_size_of_constraint = PetscMax(size_of_constraint,max_size_of_constraint);
3016674ae819SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
3017674ae819SStefano Zampini     }
3018811e8ca2SStefano Zampini     if (constraints_idx) {
3019785e854fSJed Brown       ierr = PetscMalloc1(n,&constraints_index);CHKERRQ(ierr);
3020785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint,&row_cmat_global_indices);CHKERRQ(ierr);
30214641a718SStefano Zampini       ierr = PetscBTCreate(local_size,&touched);CHKERRQ(ierr);
3022674ae819SStefano Zampini       n = 0;
3023674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
3024674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
3025674ae819SStefano Zampini         if (size_of_constraint > 1) {
3026674ae819SStefano Zampini           ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
302782d3d8afSStefano Zampini           /* find first untouched local node */
302882d3d8afSStefano Zampini           j = 0;
30294641a718SStefano Zampini           while (PetscBTLookup(touched,row_cmat_indices[j])) j++;
303082d3d8afSStefano Zampini           min_index = row_cmat_global_indices[j];
303182d3d8afSStefano Zampini           min_loc = j;
303282d3d8afSStefano Zampini           /* search the minimum among nodes not yet touched on the connected component
303382d3d8afSStefano Zampini              since there can be more than one constraint on a single cc */
3034674ae819SStefano Zampini           for (j=1;j<size_of_constraint;j++) {
30354641a718SStefano Zampini             if (!PetscBTLookup(touched,row_cmat_indices[j]) && min_index > row_cmat_global_indices[j]) {
3036674ae819SStefano Zampini               min_index = row_cmat_global_indices[j];
3037674ae819SStefano Zampini               min_loc = j;
3038674ae819SStefano Zampini             }
3039674ae819SStefano Zampini           }
30404641a718SStefano Zampini           ierr = PetscBTSet(touched,row_cmat_indices[min_loc]);CHKERRQ(ierr);
3041674ae819SStefano Zampini           constraints_index[n++] = row_cmat_indices[min_loc];
3042674ae819SStefano Zampini         }
3043674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
3044674ae819SStefano Zampini       }
30454641a718SStefano Zampini       ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
3046674ae819SStefano Zampini       ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
3047811e8ca2SStefano Zampini     }
3048811e8ca2SStefano Zampini   }
3049674ae819SStefano Zampini   *n_constraints = n;
3050811e8ca2SStefano Zampini   if (constraints_idx) *constraints_idx = constraints_index;
3051674ae819SStefano Zampini   PetscFunctionReturn(0);
3052674ae819SStefano Zampini }
3053674ae819SStefano Zampini 
3054674ae819SStefano Zampini #undef __FUNCT__
3055674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3056674ae819SStefano 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[])
3057674ae819SStefano Zampini {
3058674ae819SStefano Zampini   Vec            local_vec,global_vec;
3059674ae819SStefano Zampini   IS             seqis,paris;
3060674ae819SStefano Zampini   VecScatter     scatter_ctx;
3061674ae819SStefano Zampini   PetscScalar    *array;
3062674ae819SStefano Zampini   PetscInt       *temp_global_dofs;
3063674ae819SStefano Zampini   PetscScalar    globalsum;
3064674ae819SStefano Zampini   PetscInt       i,j,s;
3065674ae819SStefano Zampini   PetscInt       nlocals,first_index,old_index,max_local;
3066674ae819SStefano Zampini   PetscMPIInt    rank_prec_comm,size_prec_comm,max_global;
3067674ae819SStefano Zampini   PetscMPIInt    *dof_sizes,*dof_displs;
3068674ae819SStefano Zampini   PetscBool      first_found;
3069674ae819SStefano Zampini   PetscErrorCode ierr;
3070674ae819SStefano Zampini 
3071674ae819SStefano Zampini   PetscFunctionBegin;
3072674ae819SStefano Zampini   /* mpi buffers */
3073b9b85e73SStefano Zampini   ierr = MPI_Comm_size(comm,&size_prec_comm);CHKERRQ(ierr);
3074b9b85e73SStefano Zampini   ierr = MPI_Comm_rank(comm,&rank_prec_comm);CHKERRQ(ierr);
3075674ae819SStefano Zampini   j = ( !rank_prec_comm ? size_prec_comm : 0);
3076785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_sizes);CHKERRQ(ierr);
3077785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_displs);CHKERRQ(ierr);
3078674ae819SStefano Zampini   /* get maximum size of subset */
3079785e854fSJed Brown   ierr = PetscMalloc1(n_local_dofs,&temp_global_dofs);CHKERRQ(ierr);
3080674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingApply(l2gmap,n_local_dofs,local_dofs,temp_global_dofs);CHKERRQ(ierr);
3081674ae819SStefano Zampini   max_local = 0;
3082b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
3083674ae819SStefano Zampini     if (max_local < temp_global_dofs[i] ) {
3084674ae819SStefano Zampini       max_local = temp_global_dofs[i];
3085674ae819SStefano Zampini     }
3086674ae819SStefano Zampini   }
3087b9b85e73SStefano Zampini   ierr = MPI_Allreduce(&max_local,&max_global,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
3088674ae819SStefano Zampini   max_global++;
3089674ae819SStefano Zampini   max_local = 0;
3090b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
3091674ae819SStefano Zampini     if (max_local < local_dofs[i] ) {
3092674ae819SStefano Zampini       max_local = local_dofs[i];
3093674ae819SStefano Zampini     }
3094674ae819SStefano Zampini   }
3095674ae819SStefano Zampini   max_local++;
3096674ae819SStefano Zampini   /* allocate workspace */
3097674ae819SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&local_vec);CHKERRQ(ierr);
3098674ae819SStefano Zampini   ierr = VecSetSizes(local_vec,PETSC_DECIDE,max_local);CHKERRQ(ierr);
3099674ae819SStefano Zampini   ierr = VecSetType(local_vec,VECSEQ);CHKERRQ(ierr);
3100674ae819SStefano Zampini   ierr = VecCreate(comm,&global_vec);CHKERRQ(ierr);
3101674ae819SStefano Zampini   ierr = VecSetSizes(global_vec,PETSC_DECIDE,max_global);CHKERRQ(ierr);
3102674ae819SStefano Zampini   ierr = VecSetType(global_vec,VECMPI);CHKERRQ(ierr);
3103674ae819SStefano Zampini   /* create scatter */
3104674ae819SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_local_dofs,local_dofs,PETSC_COPY_VALUES,&seqis);CHKERRQ(ierr);
3105674ae819SStefano Zampini   ierr = ISCreateGeneral(comm,n_local_dofs,temp_global_dofs,PETSC_COPY_VALUES,&paris);CHKERRQ(ierr);
3106674ae819SStefano Zampini   ierr = VecScatterCreate(local_vec,seqis,global_vec,paris,&scatter_ctx);CHKERRQ(ierr);
3107674ae819SStefano Zampini   ierr = ISDestroy(&seqis);CHKERRQ(ierr);
3108674ae819SStefano Zampini   ierr = ISDestroy(&paris);CHKERRQ(ierr);
3109674ae819SStefano Zampini   /* init array */
3110674ae819SStefano Zampini   ierr = VecSet(global_vec,0.0);CHKERRQ(ierr);
3111674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
3112674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
3113674ae819SStefano Zampini   if (local_dofs_mult) {
3114674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
3115674ae819SStefano Zampini       array[local_dofs[i]]=(PetscScalar)local_dofs_mult[i];
3116674ae819SStefano Zampini     }
3117674ae819SStefano Zampini   } else {
3118674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
3119674ae819SStefano Zampini       array[local_dofs[i]]=1.0;
3120674ae819SStefano Zampini     }
3121674ae819SStefano Zampini   }
3122674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
3123674ae819SStefano Zampini   /* scatter into global vec and get total number of global dofs */
3124674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3125674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3126674ae819SStefano Zampini   ierr = VecSum(global_vec,&globalsum);CHKERRQ(ierr);
31275b08dc53SStefano Zampini   *n_global_subset = (PetscInt)PetscRealPart(globalsum);
3128674ae819SStefano Zampini   /* Fill global_vec with cumulative function for global numbering */
3129674ae819SStefano Zampini   ierr = VecGetArray(global_vec,&array);CHKERRQ(ierr);
3130674ae819SStefano Zampini   ierr = VecGetLocalSize(global_vec,&s);CHKERRQ(ierr);
3131674ae819SStefano Zampini   nlocals = 0;
3132674ae819SStefano Zampini   first_index = -1;
3133674ae819SStefano Zampini   first_found = PETSC_FALSE;
3134674ae819SStefano Zampini   for (i=0;i<s;i++) {
3135b9b85e73SStefano Zampini     if (!first_found && PetscRealPart(array[i]) > 0.1) {
3136674ae819SStefano Zampini       first_found = PETSC_TRUE;
3137674ae819SStefano Zampini       first_index = i;
3138674ae819SStefano Zampini     }
31395b08dc53SStefano Zampini     nlocals += (PetscInt)PetscRealPart(array[i]);
3140674ae819SStefano Zampini   }
3141674ae819SStefano Zampini   ierr = MPI_Gather(&nlocals,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
3142674ae819SStefano Zampini   if (!rank_prec_comm) {
3143674ae819SStefano Zampini     dof_displs[0]=0;
3144674ae819SStefano Zampini     for (i=1;i<size_prec_comm;i++) {
3145674ae819SStefano Zampini       dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
3146674ae819SStefano Zampini     }
3147674ae819SStefano Zampini   }
3148674ae819SStefano Zampini   ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&nlocals,1,MPIU_INT,0,comm);CHKERRQ(ierr);
3149674ae819SStefano Zampini   if (first_found) {
3150674ae819SStefano Zampini     array[first_index] += (PetscScalar)nlocals;
3151674ae819SStefano Zampini     old_index = first_index;
3152674ae819SStefano Zampini     for (i=first_index+1;i<s;i++) {
3153b9b85e73SStefano Zampini       if (PetscRealPart(array[i]) > 0.1) {
3154674ae819SStefano Zampini         array[i] += array[old_index];
3155674ae819SStefano Zampini         old_index = i;
3156674ae819SStefano Zampini       }
3157674ae819SStefano Zampini     }
3158674ae819SStefano Zampini   }
3159674ae819SStefano Zampini   ierr = VecRestoreArray(global_vec,&array);CHKERRQ(ierr);
3160674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
3161674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3162674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3163674ae819SStefano Zampini   /* get global ordering of local dofs */
3164674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
3165674ae819SStefano Zampini   if (local_dofs_mult) {
3166674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
31675b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-local_dofs_mult[i];
3168674ae819SStefano Zampini     }
3169674ae819SStefano Zampini   } else {
3170674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
31715b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-1;
3172674ae819SStefano Zampini     }
3173674ae819SStefano Zampini   }
3174674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
3175674ae819SStefano Zampini   /* free workspace */
3176674ae819SStefano Zampini   ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
3177674ae819SStefano Zampini   ierr = VecDestroy(&local_vec);CHKERRQ(ierr);
3178674ae819SStefano Zampini   ierr = VecDestroy(&global_vec);CHKERRQ(ierr);
3179674ae819SStefano Zampini   ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
3180674ae819SStefano Zampini   ierr = PetscFree(dof_displs);CHKERRQ(ierr);
3181674ae819SStefano Zampini   /* return pointer to global ordering of local dofs */
3182674ae819SStefano Zampini   *global_numbering_subset = temp_global_dofs;
3183674ae819SStefano Zampini   PetscFunctionReturn(0);
3184674ae819SStefano Zampini }
31859a7d3425SStefano Zampini 
31869a7d3425SStefano Zampini #undef __FUNCT__
31879a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
31889a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
31899a7d3425SStefano Zampini {
31909a7d3425SStefano Zampini   PetscInt       i,j;
31919a7d3425SStefano Zampini   PetscScalar    *alphas;
31929a7d3425SStefano Zampini   PetscErrorCode ierr;
31939a7d3425SStefano Zampini 
31949a7d3425SStefano Zampini   PetscFunctionBegin;
31959a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
3196785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
31979a7d3425SStefano Zampini   for (i=0;i<n;i++) {
31989a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
31999a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
32009a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
32019a7d3425SStefano Zampini   }
32029a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
32039a7d3425SStefano Zampini   PetscFunctionReturn(0);
32049a7d3425SStefano Zampini }
32059a7d3425SStefano Zampini 
3206e7931f94SStefano Zampini #undef __FUNCT__
320770cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
320828143c3dSStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscBool contiguous, IS* is_sends)
3209e7931f94SStefano Zampini {
3210e7931f94SStefano Zampini   Mat             subdomain_adj;
3211e7931f94SStefano Zampini   IS              new_ranks,ranks_send_to;
3212e7931f94SStefano Zampini   MatPartitioning partitioner;
3213e7931f94SStefano Zampini   Mat_IS          *matis;
3214e7931f94SStefano Zampini   PetscInt        n_neighs,*neighs,*n_shared,**shared;
3215e7931f94SStefano Zampini   PetscInt        prank;
3216e7931f94SStefano Zampini   PetscMPIInt     size,rank,color;
3217e7931f94SStefano Zampini   PetscInt        *xadj,*adjncy,*oldranks;
3218e7931f94SStefano Zampini   PetscInt        *adjncy_wgt,*v_wgt,*is_indices,*ranks_send_to_idx;
32193837a79fSStefano Zampini   PetscInt        i,local_size,threshold=0;
3220e7931f94SStefano Zampini   PetscErrorCode  ierr;
32212b510759SStefano Zampini   PetscBool       use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
3222e7931f94SStefano Zampini   PetscSubcomm    subcomm;
3223a57a6d2fSStefano Zampini 
3224e7931f94SStefano Zampini   PetscFunctionBegin;
32252b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
32262b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
32272b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
3228e7931f94SStefano Zampini 
3229e7931f94SStefano Zampini   /* Get info on mapping */
3230e7931f94SStefano Zampini   matis = (Mat_IS*)(mat->data);
3231e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&local_size);CHKERRQ(ierr);
3232e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3233e7931f94SStefano Zampini 
3234e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
3235785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
3236e7931f94SStefano Zampini   xadj[0] = 0;
3237e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
3238785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
3239785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
3240e7931f94SStefano Zampini 
32412b510759SStefano Zampini   if (threshold) {
3242d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
32432b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3244d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3245d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3246d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3247d023bfaeSStefano Zampini         xadj_count++;
3248e7931f94SStefano Zampini       }
3249e7931f94SStefano Zampini     }
3250d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3251c8587f34SStefano Zampini   } else {
3252e7931f94SStefano Zampini     if (xadj[1]) {
3253e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3254e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3255c8587f34SStefano Zampini     }
3256e7931f94SStefano Zampini   }
3257e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3258e7931f94SStefano Zampini   if (use_square) {
3259e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3260e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3261e7931f94SStefano Zampini     }
3262e7931f94SStefano Zampini   }
3263e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3264e7931f94SStefano Zampini 
32653837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3266e7931f94SStefano Zampini 
3267e7931f94SStefano Zampini   /*
3268e7931f94SStefano Zampini     Restrict work on active processes only.
3269e7931f94SStefano Zampini   */
3270e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3271e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3272e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
32732b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3274d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3275e7931f94SStefano Zampini   if (color) {
3276e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3277e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3278e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3279c8587f34SStefano Zampini   } else {
328028143c3dSStefano Zampini     PetscInt coarsening_ratio;
3281e7931f94SStefano Zampini     ierr = MPI_Comm_size(subcomm->comm,&size);CHKERRQ(ierr);
3282785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3283e7931f94SStefano Zampini     prank = rank;
3284e7931f94SStefano Zampini     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm->comm);CHKERRQ(ierr);
32858002ef2cSStefano Zampini     /*
3286e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3287e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3288c8587f34SStefano Zampini     }
32898002ef2cSStefano Zampini     */
3290e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3291e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3292c8587f34SStefano Zampini     }
3293e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3294e7931f94SStefano Zampini     ierr = MatCreateMPIAdj(subcomm->comm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
329522b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3296e7931f94SStefano Zampini 
3297e7931f94SStefano Zampini     /* Partition */
3298e7931f94SStefano Zampini     ierr = MatPartitioningCreate(subcomm->comm,&partitioner);CHKERRQ(ierr);
3299e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3300e7931f94SStefano Zampini     if (use_vwgt) {
33013837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3302e7931f94SStefano Zampini       v_wgt[0] = local_size;
3303e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3304c8587f34SStefano Zampini     }
330528143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
330628143c3dSStefano Zampini     coarsening_ratio = size/n_subdomains;
330728143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3308e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3309e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
331022b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3311e7931f94SStefano Zampini 
3312e7931f94SStefano Zampini     ierr = ISGetIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
331328143c3dSStefano Zampini     if (contiguous) {
331428143c3dSStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]]; /* contiguos set of processes */
331528143c3dSStefano Zampini     } else {
331684ba6060SStefano Zampini       ranks_send_to_idx[0] = coarsening_ratio*oldranks[is_indices[0]]; /* scattered set of processes */
331728143c3dSStefano Zampini     }
3318e7931f94SStefano Zampini     ierr = ISRestoreIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3319e7931f94SStefano Zampini     /* clean up */
3320e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
3321e7931f94SStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
3322e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3323e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3324e7931f94SStefano Zampini   }
3325e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3326e7931f94SStefano Zampini 
3327e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3328e7931f94SStefano Zampini   i = 1;
3329e7931f94SStefano Zampini   if (color) i=0;
3330e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3331e7931f94SStefano Zampini 
3332e7931f94SStefano Zampini   /* get back IS */
3333e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3334e7931f94SStefano Zampini   PetscFunctionReturn(0);
3335e7931f94SStefano Zampini }
3336e7931f94SStefano Zampini 
3337e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3338e7931f94SStefano Zampini 
3339e7931f94SStefano Zampini #undef __FUNCT__
3340e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
334128143c3dSStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
3342e7931f94SStefano Zampini {
334370cf5478SStefano Zampini   Mat                    local_mat;
3344e7931f94SStefano Zampini   Mat_IS                 *matis;
3345e7931f94SStefano Zampini   IS                     is_sends_internal;
33469d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
334728143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
33489d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3349e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3350e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3351e7931f94SStefano Zampini   const PetscInt*        is_indices;
3352e7931f94SStefano Zampini   MatType                new_local_type;
3353e7931f94SStefano Zampini   /* buffers */
3354e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
335528143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
33569d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3357e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3358e7931f94SStefano Zampini   /* MPI */
335928143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
336028143c3dSStefano Zampini   PetscSubcomm           subcomm;
3361e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
336228143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
336328143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
336428143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
336528143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
336628143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3367e7931f94SStefano Zampini   PetscErrorCode         ierr;
3368e7931f94SStefano Zampini 
3369e7931f94SStefano Zampini   PetscFunctionBegin;
337028143c3dSStefano Zampini   /* TODO: add missing checks */
337128143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
337228143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
337328143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
337428143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3375e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
337628143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3377e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3378e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3379e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3380e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3381e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
338228143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
338370cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
338470cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
338528143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
338670cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
338770cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
338870cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
338970cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
339070cf5478SStefano Zampini   }
3391e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3392e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3393e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3394e7931f94SStefano Zampini   if (!is_sends) {
339528143c3dSStefano Zampini     PetscBool pcontig = PETSC_TRUE;
339628143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
339728143c3dSStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,pcontig,&is_sends_internal);CHKERRQ(ierr);
3398c8587f34SStefano Zampini   } else {
3399e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3400e7931f94SStefano Zampini     is_sends_internal = is_sends;
3401c8587f34SStefano Zampini   }
3402e7931f94SStefano Zampini 
3403e7931f94SStefano Zampini   /* get pointer of MATIS data */
3404e7931f94SStefano Zampini   matis = (Mat_IS*)mat->data;
3405e7931f94SStefano Zampini 
3406e7931f94SStefano Zampini   /* get comm */
3407a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3408e7931f94SStefano Zampini 
3409e7931f94SStefano Zampini   /* compute number of sends */
3410e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3411e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3412e7931f94SStefano Zampini 
3413e7931f94SStefano Zampini   /* compute number of receives */
3414e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3415785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3416e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3417e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3418e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3419e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3420e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3421e7931f94SStefano Zampini 
342228143c3dSStefano Zampini   /* restrict comm if requested */
342328143c3dSStefano Zampini   subcomm = 0;
342428143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
342528143c3dSStefano Zampini   if (restrict_comm) {
342628143c3dSStefano Zampini     PetscMPIInt color,rank,subcommsize;
342728143c3dSStefano Zampini     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
342828143c3dSStefano Zampini     color = 0;
342928143c3dSStefano Zampini     if (n_sends && !n_recvs) color = 1; /* sending only processes will not partecipate in new comm */
343028143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
343128143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
343228143c3dSStefano Zampini     /* check if reuse has been requested */
343328143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
343428143c3dSStefano Zampini       if (*mat_n) {
343528143c3dSStefano Zampini         PetscMPIInt subcommsize2;
343628143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
343728143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
343828143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
343928143c3dSStefano Zampini       } else {
344028143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
344128143c3dSStefano Zampini       }
344228143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
344328143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
344428143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
344528143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
344628143c3dSStefano Zampini       comm_n = subcomm->comm;
344728143c3dSStefano Zampini     }
344828143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
344928143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
345028143c3dSStefano Zampini   } else {
345128143c3dSStefano Zampini     comm_n = comm;
345228143c3dSStefano Zampini   }
345328143c3dSStefano Zampini 
3454e7931f94SStefano Zampini   /* prepare send/receive buffers */
3455785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
3456e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
3457785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
3458e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
345928143c3dSStefano Zampini   if (nis) {
3460854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
346128143c3dSStefano Zampini   }
3462e7931f94SStefano Zampini 
346328143c3dSStefano Zampini   /* Get data from local matrices */
3464e7931f94SStefano Zampini   if (!isdense) {
3465a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
3466e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
3467e7931f94SStefano Zampini     /*
3468e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
3469e7931f94SStefano Zampini        send_buffer_idxs should contain:
3470e7931f94SStefano Zampini        - MatType_PRIVATE type
3471e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
3472e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
3473e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
3474e7931f94SStefano Zampini     */
3475e7931f94SStefano Zampini   } else {
3476e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3477e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&i);CHKERRQ(ierr);
3478854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
3479e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
3480e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
3481e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3482e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
3483e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3484e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
3485e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
3486e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
3487e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
3488c8587f34SStefano Zampini     }
3489c8587f34SStefano Zampini   }
3490e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
349128143c3dSStefano Zampini   /* additional is (if any) */
349228143c3dSStefano Zampini   if (nis) {
349328143c3dSStefano Zampini     PetscMPIInt psum;
349428143c3dSStefano Zampini     PetscInt j;
349528143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
349628143c3dSStefano Zampini       PetscInt plen;
349728143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
349828143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
349928143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
350028143c3dSStefano Zampini     }
3501854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
350228143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
350328143c3dSStefano Zampini       PetscInt plen;
350428143c3dSStefano Zampini       const PetscInt *is_array_idxs;
350528143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
350628143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
350728143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
350828143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
350928143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
351028143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
351128143c3dSStefano Zampini     }
351228143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
351328143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
351428143c3dSStefano Zampini     }
351528143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
351628143c3dSStefano Zampini   }
351728143c3dSStefano Zampini 
3518e7931f94SStefano Zampini   buf_size_idxs = 0;
3519e7931f94SStefano Zampini   buf_size_vals = 0;
352028143c3dSStefano Zampini   buf_size_idxs_is = 0;
3521e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3522e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
3523e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
352428143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
3525e7931f94SStefano Zampini   }
3526785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
3527785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
352895ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
3529e7931f94SStefano Zampini 
3530e7931f94SStefano Zampini   /* get new tags for clean communications */
3531e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
3532e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
353328143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
3534e7931f94SStefano Zampini 
3535e7931f94SStefano Zampini   /* allocate for requests */
3536785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
3537785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
353895ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
3539785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
3540785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
354195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
3542e7931f94SStefano Zampini 
3543e7931f94SStefano Zampini   /* communications */
3544e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
3545e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
354628143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
3547e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3548e7931f94SStefano Zampini     source_dest = onodes[i];
3549e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
3550e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
3551e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3552e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
355328143c3dSStefano Zampini     if (nis) {
355428143c3dSStefano 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);
355528143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
355628143c3dSStefano Zampini     }
3557e7931f94SStefano Zampini   }
3558e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
3559e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
3560e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
3561e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
356228143c3dSStefano Zampini     if (nis) {
356328143c3dSStefano 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);
356428143c3dSStefano Zampini     }
3565e7931f94SStefano Zampini   }
3566e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3567e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
3568e7931f94SStefano Zampini 
3569e7931f94SStefano Zampini   /* assemble new l2g map */
3570e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3571e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
35729d30be91SStefano Zampini   new_local_rows = 0;
3573e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
35749d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3575e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3576e7931f94SStefano Zampini   }
35779d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
3578e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
35799d30be91SStefano Zampini   new_local_rows = 0;
3580e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
35819d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
35829d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3583e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3584e7931f94SStefano Zampini   }
35859d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
35869d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
3587e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
3588e7931f94SStefano Zampini 
3589e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
3590e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
3591e7931f94SStefano 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) */
3592e7931f94SStefano Zampini   if (n_recvs) {
359328143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
3594e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
3595e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
3596e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
3597e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
3598e7931f94SStefano Zampini         break;
3599e7931f94SStefano Zampini       }
3600e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
3601e7931f94SStefano Zampini     }
3602e7931f94SStefano Zampini     switch (new_local_type_private) {
360328143c3dSStefano Zampini       case MATDENSE_PRIVATE:
360428143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
3605e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
3606e7931f94SStefano Zampini           bs = 1;
360728143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
360828143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
360928143c3dSStefano Zampini           bs = 1;
361028143c3dSStefano Zampini         }
3611e7931f94SStefano Zampini         break;
3612e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
3613e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
3614e7931f94SStefano Zampini         bs = 1;
3615e7931f94SStefano Zampini         break;
3616e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
3617e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
3618e7931f94SStefano Zampini         break;
3619e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
3620e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
3621e7931f94SStefano Zampini         break;
3622e7931f94SStefano Zampini       default:
36239d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
3624e7931f94SStefano Zampini         break;
3625e7931f94SStefano Zampini     }
362628143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
362728143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
362828143c3dSStefano Zampini     bs = 1;
3629e7931f94SStefano Zampini   }
3630e7931f94SStefano Zampini 
363170cf5478SStefano Zampini   /* create MATIS object if needed */
363270cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
3633e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
363428143c3dSStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,mat_n);CHKERRQ(ierr);
363570cf5478SStefano Zampini   } else {
363670cf5478SStefano Zampini     /* it also destroys the local matrices */
363770cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
363870cf5478SStefano Zampini   }
363970cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
3640e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
36419d30be91SStefano Zampini 
36429d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
36439d30be91SStefano Zampini 
36449d30be91SStefano Zampini   /* Global to local map of received indices */
36459d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
36469d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
36479d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
36489d30be91SStefano Zampini 
36499d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
36509d30be91SStefano Zampini   buf_size_idxs = 0;
36519d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
36529d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
36539d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
36549d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
36559d30be91SStefano Zampini   }
36569d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
36579d30be91SStefano Zampini 
36589d30be91SStefano Zampini   /* set preallocation */
36599d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
36609d30be91SStefano Zampini   if (!newisdense) {
36619d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
36629d30be91SStefano Zampini 
36639d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
36649d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
36659d30be91SStefano Zampini     if (n_recvs) {
36669d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
36679d30be91SStefano Zampini     }
36689d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
36699d30be91SStefano Zampini       PetscInt j;
36709d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
36719d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
36729d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
36739d30be91SStefano Zampini         }
36749d30be91SStefano Zampini       } else {
36759d30be91SStefano Zampini         /* TODO */
36769d30be91SStefano Zampini       }
36779d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
36789d30be91SStefano Zampini     }
36799d30be91SStefano Zampini     if (new_local_nnz) {
36809d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
36819d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
36829d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
36839d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
36849d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
36859d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
36869d30be91SStefano Zampini     } else {
36879d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
36889d30be91SStefano Zampini     }
36899d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
36909d30be91SStefano Zampini   } else {
36919d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
36929d30be91SStefano Zampini   }
3693e7931f94SStefano Zampini 
3694e7931f94SStefano Zampini   /* set values */
3695e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
36969d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
3697e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3698e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
3699e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
37009d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
3701e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3702e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3703e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
370428143c3dSStefano Zampini     } else {
370528143c3dSStefano Zampini       /* TODO */
3706e7931f94SStefano Zampini     }
3707e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3708e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
3709e7931f94SStefano Zampini   }
3710e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3711e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
371270cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
371370cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
37149d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
37159d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
3716e7931f94SStefano Zampini 
3717dfd14d43SStefano Zampini #if 0
371828143c3dSStefano Zampini   if (!restrict_comm) { /* check */
3719e7931f94SStefano Zampini     Vec       lvec,rvec;
3720e7931f94SStefano Zampini     PetscReal infty_error;
3721e7931f94SStefano Zampini 
37222a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
3723e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
3724e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
3725e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
372670cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
3727e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3728e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
3729e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
3730e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
3731e7931f94SStefano Zampini   }
373228143c3dSStefano Zampini #endif
3733e7931f94SStefano Zampini 
373428143c3dSStefano Zampini   /* assemble new additional is (if any) */
373528143c3dSStefano Zampini   if (nis) {
373628143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
373728143c3dSStefano Zampini 
373828143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3739854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
374028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
374128143c3dSStefano Zampini     psum = 0;
374228143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
374328143c3dSStefano Zampini       for (j=0;j<nis;j++) {
374428143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
374528143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
374628143c3dSStefano Zampini         psum += plen;
374728143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
374828143c3dSStefano Zampini       }
374928143c3dSStefano Zampini     }
3750854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
3751854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
375228143c3dSStefano Zampini     for (i=1;i<nis;i++) {
375328143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
375428143c3dSStefano Zampini     }
375528143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
375628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
375728143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
375828143c3dSStefano Zampini       for (j=0;j<nis;j++) {
375928143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
376028143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
376128143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
376228143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
376328143c3dSStefano Zampini       }
376428143c3dSStefano Zampini     }
376528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
376628143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
376728143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
376828143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
376928143c3dSStefano Zampini     }
377028143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
377128143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
377228143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
377328143c3dSStefano Zampini   }
3774e7931f94SStefano Zampini   /* free workspace */
377528143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
3776e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3777e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
3778e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3779e7931f94SStefano Zampini   if (isdense) {
3780e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3781e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3782e7931f94SStefano Zampini   } else {
3783e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
3784e7931f94SStefano Zampini   }
378528143c3dSStefano Zampini   if (nis) {
378628143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
378728143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
378828143c3dSStefano Zampini   }
3789e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
3790e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
379128143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
3792e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
3793e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
379428143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
3795e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
3796e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
3797e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
3798e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
3799e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
380028143c3dSStefano Zampini   if (nis) {
380128143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
380228143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
380328143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
380428143c3dSStefano Zampini   }
380528143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
380628143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
380728143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
380828143c3dSStefano Zampini     for (i=0;i<nis;i++) {
380928143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
381028143c3dSStefano Zampini     }
381128143c3dSStefano Zampini   }
3812e7931f94SStefano Zampini   PetscFunctionReturn(0);
3813e7931f94SStefano Zampini }
3814a57a6d2fSStefano Zampini 
381512edc857SStefano Zampini /* temporary hack into ksp private data structure */
381612edc857SStefano Zampini #include <petsc-private/kspimpl.h>
381712edc857SStefano Zampini 
3818c8587f34SStefano Zampini #undef __FUNCT__
3819c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
3820c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
3821c8587f34SStefano Zampini {
3822c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
3823c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
382420a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
38259881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
382620a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
38276e683305SStefano Zampini   IS                     coarse_is,*isarray;
38286e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
38296e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
3830f9eb5b7dSStefano Zampini   PC                     pc_temp;
3831c8587f34SStefano Zampini   PCType                 coarse_pc_type;
3832c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
3833f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
38344f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
38356e683305SStefano Zampini   Mat                    t_coarse_mat_is;
38366e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
38376e683305SStefano Zampini   PetscMPIInt            all_procs;
383874e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
383968457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
384022bc73bbSStefano Zampini   PetscScalar            *array;
38419881197aSStefano Zampini   PetscErrorCode         ierr;
3842fdc09c96SStefano Zampini 
3843c8587f34SStefano Zampini   PetscFunctionBegin;
3844c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
384568457ee5SStefano 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 */
384668457ee5SStefano Zampini     compute_vecs = PETSC_TRUE;
3847fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
3848fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
3849f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
3850f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
3851f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
3852fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
3853fa7f1dd8SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size) { /* ...but with different size, so reset it and set reuse flag to false */
3854727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3855fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
3856fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
3857fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
3858f4ddd8eeSStefano Zampini       }
3859fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
3860fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
3861f4ddd8eeSStefano Zampini     }
386270cf5478SStefano Zampini     /* reset any subassembling information */
386370cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
38646e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
38656e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
3866fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
3867f4ddd8eeSStefano Zampini   }
3868c8587f34SStefano Zampini 
38696e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
38702b510759SStefano Zampini   im_active = !!(pcis->n);
38712b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
38726e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
38736e683305SStefano Zampini   void_procs = all_procs-active_procs;
38746e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
387574e2c79eSStefano Zampini   redist = PETSC_FALSE;
387622bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
38776e683305SStefano Zampini     csin_ml = PETSC_TRUE;
38786e683305SStefano Zampini     ncoarse_ml = void_procs;
38796e683305SStefano Zampini     csin_ds = PETSC_TRUE;
38806e683305SStefano Zampini     ncoarse_ds = void_procs;
38816e683305SStefano Zampini   } else {
38826e683305SStefano Zampini     csin_ml = PETSC_FALSE;
38836e683305SStefano Zampini     ncoarse_ml = all_procs;
38846e683305SStefano Zampini     if (void_procs) {
38856e683305SStefano Zampini       csin_ds = PETSC_TRUE;
38866e683305SStefano Zampini       ncoarse_ds = void_procs;
38876e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
38886e683305SStefano Zampini     } else {
388974e2c79eSStefano Zampini       if (pcbddc->redistribute_coarse && pcbddc->redistribute_coarse < all_procs) {
389074e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
389174e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
389274e2c79eSStefano Zampini         redist = PETSC_TRUE;
389374e2c79eSStefano Zampini       } else {
38946e683305SStefano Zampini         csin_ds = PETSC_FALSE;
38956e683305SStefano Zampini         ncoarse_ds = all_procs;
38966e683305SStefano Zampini       }
38976e683305SStefano Zampini     }
389874e2c79eSStefano Zampini   }
38996e683305SStefano Zampini 
39006e683305SStefano Zampini   /*
39016e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
39026e683305SStefano Zampini     - we have not exceeded the number of levels requested
39036e683305SStefano Zampini     - we can actually subassemble the active processes
39046e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
39056e683305SStefano Zampini   */
39066e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
39076e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
39086e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
39096e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
39106e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
3911f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
39122b510759SStefano Zampini     } else {
3913f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
3914c8587f34SStefano Zampini     }
3915c8587f34SStefano Zampini   }
39166e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
39176e683305SStefano Zampini   if (multilevel_allowed) {
39186e683305SStefano Zampini     ncoarse = ncoarse_ml;
39196e683305SStefano Zampini     csin = csin_ml;
39206e683305SStefano Zampini   } else {
39216e683305SStefano Zampini     ncoarse = ncoarse_ds;
39226e683305SStefano Zampini     csin = csin_ds;
39236e683305SStefano Zampini   }
3924e7931f94SStefano Zampini 
3925abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
3926abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
3927abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
3928abbbba34SStefano Zampini 
3929abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
393022bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
393122bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
393222bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
393322bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
3934b9b85e73SStefano Zampini #if 0
3935b9b85e73SStefano Zampini   {
3936b9b85e73SStefano Zampini     PetscViewer viewer;
3937b9b85e73SStefano Zampini     char filename[256];
3938b9b85e73SStefano Zampini     sprintf(filename,"local_coarse_mat%d.m",PetscGlobalRank);
3939b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3940b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3941b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
3942b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3943b9b85e73SStefano Zampini   }
3944b9b85e73SStefano Zampini #endif
39456e683305SStefano 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);
39466e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
39476e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
39486e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3949abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
3950abbbba34SStefano Zampini 
39516e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
39526e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
39536e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
39546e683305SStefano Zampini     const PetscInt         *idxs;
39556e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
39566e683305SStefano Zampini 
39576e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
39580be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
39596e683305SStefano Zampini     /* allocate space for temporary storage */
3960854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
3961854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
39626e683305SStefano Zampini     /* allocate for IS array */
39636e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
39646e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
39656e683305SStefano Zampini     nis = nisdofs + nisneu;
3966854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
39676e683305SStefano Zampini     /* dofs splitting */
39686e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
39696e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
39706e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
39716e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
39726e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
39736e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
39746e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
39756e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
39766e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
39776e683305SStefano Zampini     }
39786e683305SStefano Zampini     /* neumann boundaries */
39796e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
39806e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
39816e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
39826e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
39836e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
39846e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
39856e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
39866e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
39876e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
39886e683305SStefano Zampini     }
39896e683305SStefano Zampini     /* free memory */
39906e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
39916e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
39926e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
39936e683305SStefano Zampini   } else {
39946e683305SStefano Zampini     nis = 0;
39956e683305SStefano Zampini     nisdofs = 0;
39966e683305SStefano Zampini     nisneu = 0;
39976e683305SStefano Zampini     isarray = NULL;
39986e683305SStefano Zampini   }
39996e683305SStefano Zampini   /* destroy no longer needed map */
40006e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
40016e683305SStefano Zampini 
40026e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
40036e683305SStefano Zampini   coarse_mat_is = NULL;
40046e683305SStefano Zampini   if (csin) {
40056e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
400674e2c79eSStefano Zampini       if (redist) {
400774e2c79eSStefano Zampini         PetscMPIInt rank;
400874e2c79eSStefano Zampini         PetscInt spc,n_spc_p1,dest[1];
400974e2c79eSStefano Zampini 
401074e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
401174e2c79eSStefano Zampini         spc = all_procs/pcbddc->redistribute_coarse;
401274e2c79eSStefano Zampini         n_spc_p1 = all_procs%pcbddc->redistribute_coarse;
401374e2c79eSStefano Zampini         if (rank > n_spc_p1*(spc+1)-1) {
401474e2c79eSStefano Zampini           dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
401574e2c79eSStefano Zampini         } else {
401674e2c79eSStefano Zampini           dest[0] = rank/(spc+1);
401774e2c79eSStefano Zampini         }
401874e2c79eSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),1,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
401974e2c79eSStefano Zampini       } else {
40206e683305SStefano Zampini         PetscInt j,tissize,*nisindices;
40216e683305SStefano Zampini         PetscInt *coarse_candidates;
40226e683305SStefano Zampini         const PetscInt* tisindices;
40236e683305SStefano Zampini         /* get coarse candidates' ranks in pc communicator */
4024854ce69bSBarry Smith         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
40256e683305SStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
40266e683305SStefano Zampini         for (i=0,j=0;i<all_procs;i++) {
40276e683305SStefano Zampini           if (!coarse_candidates[i]) {
40286e683305SStefano Zampini             coarse_candidates[j]=i;
40296e683305SStefano Zampini             j++;
40306e683305SStefano Zampini           }
40316e683305SStefano Zampini         }
40326e683305SStefano Zampini         if (j < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",j,ncoarse);
40336e683305SStefano Zampini         /* get a suitable subassembling pattern */
40346e683305SStefano Zampini         if (csin_type_simple) {
40356e683305SStefano Zampini           PetscMPIInt rank;
40366e683305SStefano Zampini           PetscInt    issize,isidx;
40376e683305SStefano Zampini           ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
40386e683305SStefano Zampini           if (im_active) {
40396e683305SStefano Zampini             issize = 1;
40406e683305SStefano Zampini             isidx = (PetscInt)rank;
40416e683305SStefano Zampini           } else {
40426e683305SStefano Zampini             issize = 0;
40436e683305SStefano Zampini             isidx = -1;
40446e683305SStefano Zampini           }
40456e683305SStefano Zampini           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
40466e683305SStefano Zampini         } else {
40476e683305SStefano Zampini           ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,PETSC_TRUE,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
40486e683305SStefano Zampini         }
40496e683305SStefano Zampini         if (pcbddc->dbg_flag) {
40506e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
40516e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
40526e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
40536e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
40546e683305SStefano Zampini           for (i=0;i<j;i++) {
40556e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
40566e683305SStefano Zampini           }
40576e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
40586e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40596e683305SStefano Zampini         }
40606e683305SStefano Zampini         /* shift the pattern on coarse candidates */
40616e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
40626e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
4063854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
40646e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
40656e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
40666e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
40676e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
40686e683305SStefano Zampini       }
406974e2c79eSStefano Zampini     }
40706e683305SStefano Zampini     if (pcbddc->dbg_flag) {
40716e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
40726e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
40736e683305SStefano Zampini       ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
40746e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40756e683305SStefano Zampini     }
40766e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
40776e683305SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
40786e683305SStefano Zampini   } else {
40796e683305SStefano Zampini     if (pcbddc->dbg_flag) {
40806e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
40816e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
40826e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40836e683305SStefano Zampini     }
40846e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
40856e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
40866e683305SStefano Zampini   }
40876e683305SStefano Zampini 
40886e683305SStefano Zampini   /* create local to global scatters for coarse problem */
408968457ee5SStefano Zampini   if (compute_vecs) {
40906e683305SStefano Zampini     PetscInt lrows;
40916e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
40926e683305SStefano Zampini     if (coarse_mat_is) {
40936e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
40946e683305SStefano Zampini     } else {
40956e683305SStefano Zampini       lrows = 0;
40966e683305SStefano Zampini     }
40976e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
40986e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
40996e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
41006e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
41016e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
41026e683305SStefano Zampini   }
41036e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
41046e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
4105c8587f34SStefano Zampini 
4106f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
4107f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
4108f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
4109f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
4110f9eb5b7dSStefano Zampini   } else {
4111f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
4112f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
4113c8587f34SStefano Zampini   }
4114c8587f34SStefano Zampini 
41156e683305SStefano Zampini   /* print some info if requested */
41166e683305SStefano Zampini   if (pcbddc->dbg_flag) {
41176e683305SStefano Zampini     if (!multilevel_allowed) {
41186e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
41196e683305SStefano Zampini       if (multilevel_requested) {
41206e683305SStefano 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);
41216e683305SStefano Zampini       } else if (pcbddc->max_levels) {
41226e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
41236e683305SStefano Zampini       }
41246e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
41256e683305SStefano Zampini     }
41266e683305SStefano Zampini   }
41276e683305SStefano Zampini 
4128f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
41296e683305SStefano Zampini   if (coarse_mat_is) {
41306e683305SStefano Zampini     MatReuse coarse_mat_reuse;
41316a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
41326e683305SStefano Zampini     if (pcbddc->dbg_flag) {
41336e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
41346e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
41356e683305SStefano Zampini     }
4136f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
4137312be037SStefano Zampini       char prefix[256],str_level[16];
4138e604994aSStefano Zampini       size_t len;
41396e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
4140c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
4141f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
41425f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
4143c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
41446e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
4145c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4146c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4147e604994aSStefano Zampini       /* prefix */
4148e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
4149e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4150e604994aSStefano Zampini       if (!pcbddc->current_level) {
4151e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4152e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
4153c8587f34SStefano Zampini       } else {
4154e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4155312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4156312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
415734d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4158312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4159e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
4160e604994aSStefano Zampini       }
4161e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
4162f9eb5b7dSStefano Zampini       /* allow user customization */
4163f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
41647e0def11SStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4165312be037SStefano Zampini     }
4166f9eb5b7dSStefano Zampini 
4167f9eb5b7dSStefano Zampini     /* get some info after set from options */
4168f9eb5b7dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4169f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
4170f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
41714f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
41726e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
4173f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4174f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
4175f9eb5b7dSStefano Zampini     }
41764f3a063dSStefano Zampini     if (isredundant) {
41774f3a063dSStefano Zampini       KSP inner_ksp;
41784f3a063dSStefano Zampini       PC inner_pc;
41794f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
41804f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
41814f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
41824f3a063dSStefano Zampini     }
4183f9eb5b7dSStefano Zampini 
41846e683305SStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
4185f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
4186f9eb5b7dSStefano Zampini     ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
4187f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
41886e683305SStefano Zampini     if (nisdofs) {
41896e683305SStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
41906e683305SStefano Zampini       for (i=0;i<nisdofs;i++) {
41916e683305SStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
41921035eff8SStefano Zampini       }
41931035eff8SStefano Zampini     }
41946e683305SStefano Zampini     if (nisneu) {
41956e683305SStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
41966e683305SStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
41971035eff8SStefano Zampini     }
4198fdc09c96SStefano Zampini 
4199f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
4200fa7f1dd8SStefano Zampini     if (coarse_reuse) {
420181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
4202fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
42036e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
4204fa7f1dd8SStefano Zampini     } else {
42056e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
4206fa7f1dd8SStefano Zampini     }
4207c8587f34SStefano Zampini     if (isbddc || isnn) {
420822bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
420970cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
421028143c3dSStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,PETSC_TRUE,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
421122b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
42126e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
42136e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
42146e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
42156e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
421622b6e8a2SStefano Zampini           }
421770cf5478SStefano Zampini         }
42186e683305SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
421970cf5478SStefano Zampini       } else {
422022bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
422122bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
422222bc73bbSStefano Zampini       }
422322bc73bbSStefano Zampini     } else {
42242e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
4225c8587f34SStefano Zampini     }
4226c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
4227c8587f34SStefano Zampini 
4228c8587f34SStefano Zampini     /* propagate symmetry info to coarse matrix */
4229b9d89cd5SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
42305a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
4231c8587f34SStefano Zampini 
42326e683305SStefano Zampini     /* set operators */
42335f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
42346e683305SStefano Zampini     if (pcbddc->dbg_flag) {
42356e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
42366e683305SStefano Zampini     }
42376e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
42386e683305SStefano Zampini     coarse_mat = 0;
42396e683305SStefano Zampini   }
42406e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
4241b9b85e73SStefano Zampini #if 0
4242b9b85e73SStefano Zampini   {
4243b9b85e73SStefano Zampini     PetscViewer viewer;
4244b9b85e73SStefano Zampini     char filename[256];
4245b9b85e73SStefano Zampini     sprintf(filename,"coarse_mat.m");
4246b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,filename,&viewer);CHKERRQ(ierr);
4247b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4248b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4249b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4250b9b85e73SStefano Zampini   }
4251b9b85e73SStefano Zampini #endif
4252c8587f34SStefano Zampini 
4253c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4254c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4255c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
425698a51de6SStefano Zampini   }
425798a51de6SStefano Zampini 
425898a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
425998a51de6SStefano Zampini     Vec crhs,csol;
426098a51de6SStefano Zampini     PetscBool ispreonly;
426198a51de6SStefano Zampini     if (CoarseNullSpace) {
4262c8587f34SStefano Zampini       if (isbddc) {
4263c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4264c8587f34SStefano Zampini       } else {
4265c8587f34SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
4266c8587f34SStefano Zampini       }
4267c8587f34SStefano Zampini     }
4268f9eb5b7dSStefano Zampini     /* setup coarse ksp */
4269f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4270f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4271f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
42726e683305SStefano Zampini     /* hack */
4273f347579bSStefano Zampini     if (!csol) {
42742a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4275f9eb5b7dSStefano Zampini     }
4276f347579bSStefano Zampini     if (!crhs) {
42772a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4278f347579bSStefano Zampini     }
4279cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4280cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
42816e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4282c8587f34SStefano Zampini       KSP       check_ksp;
42832b510759SStefano Zampini       KSPType   check_ksp_type;
4284c8587f34SStefano Zampini       PC        check_pc;
42856e683305SStefano Zampini       Vec       check_vec,coarse_vec;
42866a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
42872b510759SStefano Zampini       PetscInt  its;
42886e683305SStefano Zampini       PetscBool compute_eigs;
42896e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
42906e683305SStefano Zampini       PetscInt  neigs;
42918e185a42SStefano Zampini       const char *prefix;
4292c8587f34SStefano Zampini 
42932b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
42946e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
429523ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4296f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
42972b510759SStefano Zampini       if (ispreonly) {
42982b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
42996e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
43002b510759SStefano Zampini       } else {
4301cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
43026e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4303c8587f34SStefano Zampini       }
4304c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
43056e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
43066e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
43076e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4308a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4309a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4310a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4311a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4312c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4313c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4314c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4315c8587f34SStefano Zampini       /* create random vec */
43166e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
43176e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
4318c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
4319c8587f34SStefano Zampini       if (CoarseNullSpace) {
4320c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
4321c8587f34SStefano Zampini       }
43226e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
4323c8587f34SStefano Zampini       /* solve coarse problem */
43246e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
4325c8587f34SStefano Zampini       if (CoarseNullSpace) {
43266e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
4327c8587f34SStefano Zampini       }
4328cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
43296e683305SStefano Zampini       if (compute_eigs) {
4330854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4331854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
43326e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
43336e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
43346e683305SStefano Zampini         lambda_min = eigs_r[0];
43356e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
43366e683305SStefano Zampini           if (lambda_max>lambda_min) {
4337cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4338cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4339cbcc2c2aSStefano Zampini           }
4340c8587f34SStefano Zampini         }
4341c8587f34SStefano Zampini       }
4342cbcc2c2aSStefano Zampini 
4343c8587f34SStefano Zampini       /* check coarse problem residual error */
43446e683305SStefano Zampini       if (pcbddc->dbg_flag) {
43456e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
43466e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
43476e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4348c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
43496e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
43506e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4351c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
43526e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (%d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
43536e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
43546e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
43556e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
43566e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
43576e683305SStefano Zampini         if (compute_eigs) {
43586e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4359deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4360c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
43616e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
43626e683305SStefano 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);
43636e683305SStefano Zampini           for (i=0;i<neigs;i++) {
43646e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4365c8587f34SStefano Zampini           }
43666e683305SStefano Zampini         }
43676e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
43686e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
43696e683305SStefano Zampini       }
4370c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
43716e683305SStefano Zampini       if (compute_eigs) {
43726e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
43736e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4374c8587f34SStefano Zampini       }
43756e683305SStefano Zampini     }
43766e683305SStefano Zampini   }
4377cbcc2c2aSStefano Zampini   /* print additional info */
4378cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
43796e683305SStefano Zampini     /* waits until all processes reaches this point */
43806e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4381cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4382cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4383cbcc2c2aSStefano Zampini   }
4384cbcc2c2aSStefano Zampini 
43852b510759SStefano Zampini   /* free memory */
4386c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4387fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4388c8587f34SStefano Zampini   PetscFunctionReturn(0);
4389c8587f34SStefano Zampini }
4390674ae819SStefano Zampini 
4391f34684f1SStefano Zampini #undef __FUNCT__
4392f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4393f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4394f34684f1SStefano Zampini {
4395f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4396f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
4397f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
4398727cdba6SStefano Zampini   PetscInt       i,coarse_size;
4399727cdba6SStefano Zampini   PetscInt       *local_primal_indices;
4400f34684f1SStefano Zampini   PetscErrorCode ierr;
4401f34684f1SStefano Zampini 
4402f34684f1SStefano Zampini   PetscFunctionBegin;
4403f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
440489c96988SStefano Zampini   if (!pcbddc->primal_indices_local_idxs && pcbddc->local_primal_size) {
440589c96988SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Local primal indices have not been created");
4406727cdba6SStefano Zampini   }
4407727cdba6SStefano 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);
4408f34684f1SStefano Zampini 
4409f34684f1SStefano Zampini   /* check numbering */
4410f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
4411f34684f1SStefano Zampini     PetscScalar coarsesum,*array;
4412b9b85e73SStefano Zampini     PetscBool set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
4413f34684f1SStefano Zampini 
4414f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4415f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4416f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
44170fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
4418f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4419f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4420727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4421f34684f1SStefano Zampini     }
4422f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4423f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4424f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4425f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4426f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4427f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4428f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4429f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4430f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4431f34684f1SStefano Zampini       if (array[i] == 1.0) {
4432b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
4433f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a single process!\n",PetscGlobalRank,i);CHKERRQ(ierr);
4434f34684f1SStefano Zampini       }
4435f34684f1SStefano Zampini     }
4436b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4437f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4438f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4439f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
4440f34684f1SStefano Zampini     }
4441f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4442f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4443f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4444f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4445f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
4446f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
4447b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
4448f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
4449f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4450f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4451f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
4452727cdba6SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i]);
4453f34684f1SStefano Zampini       }
4454f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4455f34684f1SStefano Zampini     }
4456f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4457b9b85e73SStefano Zampini     if (set_error_reduced) {
4458b9b85e73SStefano Zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
4459b9b85e73SStefano Zampini     }
4460f34684f1SStefano Zampini   }
4461f34684f1SStefano Zampini   /* get back data */
4462f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
4463f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
4464674ae819SStefano Zampini   PetscFunctionReturn(0);
4465674ae819SStefano Zampini }
4466674ae819SStefano Zampini 
4467e456f2a8SStefano Zampini #undef __FUNCT__
4468e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
4469a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
4470e456f2a8SStefano Zampini {
4471e456f2a8SStefano Zampini   IS             localis_t;
4472a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
4473e456f2a8SStefano Zampini   PetscScalar    *vals;
4474e456f2a8SStefano Zampini   PetscErrorCode ierr;
4475e456f2a8SStefano Zampini 
4476e456f2a8SStefano Zampini   PetscFunctionBegin;
4477a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
4478e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
4479854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
4480e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
4481e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4482a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
4483a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
44841035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
4485a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
44861035eff8SStefano Zampini   }
4487a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
4488e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4489e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
4490a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
4491a7dc3881SStefano Zampini   /* now compute set in local ordering */
4492a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4493a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4494a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4495a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
4496a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4497ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4498e456f2a8SStefano Zampini       lsize++;
4499e456f2a8SStefano Zampini     }
4500e456f2a8SStefano Zampini   }
4501854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
4502a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4503ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4504e456f2a8SStefano Zampini       idxs[lsize++] = i;
4505e456f2a8SStefano Zampini     }
4506e456f2a8SStefano Zampini   }
4507a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4508a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
4509e456f2a8SStefano Zampini   *localis = localis_t;
4510e456f2a8SStefano Zampini   PetscFunctionReturn(0);
4511e456f2a8SStefano Zampini }
4512906d46d4SStefano Zampini 
4513906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
4514906d46d4SStefano Zampini #undef __FUNCT__
4515906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
4516906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
4517906d46d4SStefano Zampini {
4518906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4519906d46d4SStefano Zampini   PetscErrorCode   ierr;
4520906d46d4SStefano Zampini 
4521906d46d4SStefano Zampini   PetscFunctionBegin;
4522906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4523906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4524906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4525906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4526906d46d4SStefano Zampini   PetscFunctionReturn(0);
4527906d46d4SStefano Zampini }
4528906d46d4SStefano Zampini 
4529906d46d4SStefano Zampini #undef __FUNCT__
4530906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
4531906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
4532906d46d4SStefano Zampini {
4533906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4534906d46d4SStefano Zampini   PetscErrorCode   ierr;
4535906d46d4SStefano Zampini 
4536906d46d4SStefano Zampini   PetscFunctionBegin;
4537906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4538906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4539906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4540906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4541906d46d4SStefano Zampini   PetscFunctionReturn(0);
4542906d46d4SStefano Zampini }
4543b96c3477SStefano Zampini 
4544b96c3477SStefano Zampini #undef __FUNCT__
4545b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
454608122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
4547b96c3477SStefano Zampini {
4548b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4549b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4550b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
4551b96c3477SStefano Zampini   PetscBool           free_used_adj;
4552b96c3477SStefano Zampini   PetscErrorCode      ierr;
4553b96c3477SStefano Zampini 
4554b96c3477SStefano Zampini   PetscFunctionBegin;
4555b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
4556b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
455708122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
4558b96c3477SStefano Zampini     used_xadj = NULL;
4559b96c3477SStefano Zampini     used_adjncy = NULL;
4560b96c3477SStefano Zampini   } else {
456108122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
456208122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
456308122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
456408122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
4565b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
4566b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
4567b96c3477SStefano Zampini     } else {
4568b96c3477SStefano Zampini       Mat            mat_adj;
4569b96c3477SStefano Zampini       PetscBool      flg_row=PETSC_TRUE;
4570b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
4571b96c3477SStefano Zampini       PetscInt       nvtxs;
4572b96c3477SStefano Zampini 
4573b96c3477SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
4574b96c3477SStefano Zampini       ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4575b96c3477SStefano Zampini       if (!flg_row) {
4576b96c3477SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
4577b96c3477SStefano Zampini       }
4578b96c3477SStefano Zampini       ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
4579b96c3477SStefano Zampini       ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
4580b96c3477SStefano Zampini       ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
4581b96c3477SStefano Zampini       ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4582b96c3477SStefano Zampini       if (!flg_row) {
4583b96c3477SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
4584b96c3477SStefano Zampini       }
4585b96c3477SStefano Zampini       ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
4586b96c3477SStefano Zampini       free_used_adj = PETSC_TRUE;
4587b96c3477SStefano Zampini     }
4588b96c3477SStefano Zampini   }
458908122e43SStefano 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);
4590b96c3477SStefano Zampini 
4591b96c3477SStefano Zampini   /* free adjacency */
4592b96c3477SStefano Zampini   if (free_used_adj) {
4593b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
4594b96c3477SStefano Zampini   }
4595b96c3477SStefano Zampini   PetscFunctionReturn(0);
4596b96c3477SStefano Zampini }
4597b96c3477SStefano Zampini 
4598b96c3477SStefano Zampini #undef __FUNCT__
4599b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
460008122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
4601b96c3477SStefano Zampini {
4602b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
4603b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4604b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4605b96c3477SStefano Zampini   PCBDDCGraph         graph;
4606b96c3477SStefano Zampini   Mat                 S_j;
4607b96c3477SStefano Zampini   PetscErrorCode      ierr;
4608b96c3477SStefano Zampini 
4609b96c3477SStefano Zampini   PetscFunctionBegin;
4610b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
461108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
4612b96c3477SStefano Zampini     IS verticesIS;
4613b96c3477SStefano Zampini 
4614b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
4615b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
4616b96c3477SStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap);CHKERRQ(ierr);
4617b96c3477SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticesIS);CHKERRQ(ierr);
4618b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4619b96c3477SStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
4620b96c3477SStefano Zampini /*
4621b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
4622b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4623b96c3477SStefano Zampini     }
4624b96c3477SStefano Zampini */
4625b96c3477SStefano Zampini   } else {
4626b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
4627b96c3477SStefano Zampini   }
4628b96c3477SStefano Zampini 
4629b96c3477SStefano Zampini   /* Create Schur complement matrix */
4630b96c3477SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
4631b96c3477SStefano Zampini   ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
4632b96c3477SStefano Zampini 
4633b96c3477SStefano Zampini   /* sub_schurs init */
463408122e43SStefano 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);
4635b96c3477SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
4636b96c3477SStefano Zampini   /* free graph struct */
463708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
4638b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
4639b96c3477SStefano Zampini   }
4640b96c3477SStefano Zampini   PetscFunctionReturn(0);
4641b96c3477SStefano Zampini }
4642