xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision a3df083a2dd58d981f643d031b2ea965535d4008)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4674ae819SStefano Zampini #include <petscblaslapack.h>
5674ae819SStefano Zampini 
6906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y);
7906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y);
8906d46d4SStefano Zampini 
9*a3df083aSStefano Zampini #undef __FUNCT__
10*a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
11*a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
12*a3df083aSStefano Zampini {
13*a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
14*a3df083aSStefano Zampini   PetscErrorCode          ierr;
15*a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
16*a3df083aSStefano Zampini 
17*a3df083aSStefano Zampini   PetscFunctionBegin;
18*a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
19*a3df083aSStefano Zampini   if (transpose) {
20*a3df083aSStefano Zampini     apply_right = ctx->apply_left;
21*a3df083aSStefano Zampini     apply_left = ctx->apply_right;
22*a3df083aSStefano Zampini   } else {
23*a3df083aSStefano Zampini     apply_right = ctx->apply_right;
24*a3df083aSStefano Zampini     apply_left = ctx->apply_left;
25*a3df083aSStefano Zampini   }
26*a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
27*a3df083aSStefano Zampini   if (apply_right) {
28*a3df083aSStefano Zampini     const PetscScalar *ax;
29*a3df083aSStefano Zampini     PetscInt          nl,i;
30*a3df083aSStefano Zampini 
31*a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
32*a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
33*a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
34*a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
35*a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
36*a3df083aSStefano Zampini       PetscScalar    sum,val;
37*a3df083aSStefano Zampini       const PetscInt *idxs;
38*a3df083aSStefano Zampini       PetscInt       nz,j;
39*a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
40*a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
41*a3df083aSStefano Zampini       sum = 0.;
42*a3df083aSStefano Zampini       if (ctx->apply_p0) {
43*a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
44*a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
45*a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
46*a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
47*a3df083aSStefano Zampini         }
48*a3df083aSStefano Zampini       } else {
49*a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
50*a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
51*a3df083aSStefano Zampini         }
52*a3df083aSStefano Zampini       }
53*a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
54*a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
55*a3df083aSStefano Zampini     }
56*a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
57*a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
58*a3df083aSStefano Zampini   }
59*a3df083aSStefano Zampini   if (transpose) {
60*a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
61*a3df083aSStefano Zampini   } else {
62*a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
63*a3df083aSStefano Zampini   }
64*a3df083aSStefano Zampini   if (reset_x) {
65*a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
66*a3df083aSStefano Zampini   }
67*a3df083aSStefano Zampini   if (apply_left) {
68*a3df083aSStefano Zampini     PetscScalar *ay;
69*a3df083aSStefano Zampini     PetscInt    i;
70*a3df083aSStefano Zampini 
71*a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
72*a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
73*a3df083aSStefano Zampini       PetscScalar    sum,val;
74*a3df083aSStefano Zampini       const PetscInt *idxs;
75*a3df083aSStefano Zampini       PetscInt       nz,j;
76*a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
77*a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
78*a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
79*a3df083aSStefano Zampini       if (ctx->apply_p0) {
80*a3df083aSStefano Zampini         sum = 0.;
81*a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
82*a3df083aSStefano Zampini           sum += ay[idxs[j]];
83*a3df083aSStefano Zampini           ay[idxs[j]] += val;
84*a3df083aSStefano Zampini         }
85*a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
86*a3df083aSStefano Zampini       } else {
87*a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
88*a3df083aSStefano Zampini           ay[idxs[j]] += val;
89*a3df083aSStefano Zampini         }
90*a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
91*a3df083aSStefano Zampini       }
92*a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
93*a3df083aSStefano Zampini     }
94*a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
95*a3df083aSStefano Zampini   }
96*a3df083aSStefano Zampini   PetscFunctionReturn(0);
97*a3df083aSStefano Zampini }
98*a3df083aSStefano Zampini 
99*a3df083aSStefano Zampini #undef __FUNCT__
100*a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
101*a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
102*a3df083aSStefano Zampini {
103*a3df083aSStefano Zampini   PetscErrorCode ierr;
104*a3df083aSStefano Zampini 
105*a3df083aSStefano Zampini   PetscFunctionBegin;
106*a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
107*a3df083aSStefano Zampini   PetscFunctionReturn(0);
108*a3df083aSStefano Zampini }
109*a3df083aSStefano Zampini 
110*a3df083aSStefano Zampini #undef __FUNCT__
111*a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
112*a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
113*a3df083aSStefano Zampini {
114*a3df083aSStefano Zampini   PetscErrorCode ierr;
115*a3df083aSStefano Zampini 
116*a3df083aSStefano Zampini   PetscFunctionBegin;
117*a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
118*a3df083aSStefano Zampini   PetscFunctionReturn(0);
119*a3df083aSStefano Zampini }
120*a3df083aSStefano Zampini 
121*a3df083aSStefano Zampini #undef __FUNCT__
122*a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
123*a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
124*a3df083aSStefano Zampini {
125*a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
126*a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
127*a3df083aSStefano Zampini   Mat_IS                  *matis = (Mat_IS*)pc->pmat->data;
128*a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
129*a3df083aSStefano Zampini   PetscErrorCode          ierr;
130*a3df083aSStefano Zampini 
131*a3df083aSStefano Zampini   PetscFunctionBegin;
132*a3df083aSStefano Zampini   if (!restore) {
133*a3df083aSStefano Zampini     Mat              A,A_IB,A_BI;
134*a3df083aSStefano Zampini     PetscScalar      *work;
135*a3df083aSStefano Zampini     PCBDDCReuseMumps reuse = pcbddc->sub_schurs->reuse_mumps;
136*a3df083aSStefano Zampini 
137*a3df083aSStefano Zampini     if (!reuse) {
138*a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot setup shell matrices!");
139*a3df083aSStefano Zampini     }
140*a3df083aSStefano Zampini 
141*a3df083aSStefano Zampini     /* local mat */
142*a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A);CHKERRQ(ierr);
143*a3df083aSStefano Zampini     ierr = MatSetSizes(A,pcis->n,pcis->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
144*a3df083aSStefano Zampini     ierr = MatSetType(A,MATSHELL);CHKERRQ(ierr);
145*a3df083aSStefano Zampini     ierr = MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
146*a3df083aSStefano Zampini     ierr = MatShellSetOperation(A,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
147*a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
148*a3df083aSStefano Zampini     ierr = MatShellSetContext(A,ctx);CHKERRQ(ierr);
149*a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
150*a3df083aSStefano Zampini     ctx->apply_right = PETSC_TRUE;
151*a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_TRUE;
152*a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
153*a3df083aSStefano Zampini     ctx->benign_zerodiag_subs = pcbddc->benign_zerodiag_subs;
154*a3df083aSStefano Zampini     ctx->A = matis->A;
155*a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
156*a3df083aSStefano Zampini     ctx->work = work;
157*a3df083aSStefano Zampini     ierr = MatSetUp(A);CHKERRQ(ierr);
158*a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
159*a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
160*a3df083aSStefano Zampini     matis->A = A;
161*a3df083aSStefano Zampini 
162*a3df083aSStefano Zampini     /* A_IB */
163*a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
164*a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
165*a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
166*a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
167*a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
168*a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
169*a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
170*a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
171*a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
172*a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
173*a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
174*a3df083aSStefano Zampini     ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
175*a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
176*a3df083aSStefano Zampini     ctx->work = work;
177*a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
178*a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179*a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180*a3df083aSStefano Zampini     pcis->A_IB = A_IB;
181*a3df083aSStefano Zampini 
182*a3df083aSStefano Zampini     /* A_BI as A_IB^T */
183*a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
184*a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
185*a3df083aSStefano Zampini     pcis->A_BI = A_BI;
186*a3df083aSStefano Zampini   } else {
187*a3df083aSStefano Zampini     ierr = MatShellGetContext(matis->A,&ctx);CHKERRQ(ierr);
188*a3df083aSStefano Zampini     ierr = MatDestroy(&matis->A);CHKERRQ(ierr);
189*a3df083aSStefano Zampini     matis->A = ctx->A;
190*a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
191*a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
192*a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
193*a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
194*a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
195*a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
196*a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
197*a3df083aSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
198*a3df083aSStefano Zampini     pcbddc->benign_original_mat = NULL;
199*a3df083aSStefano Zampini   }
200*a3df083aSStefano Zampini   PetscFunctionReturn(0);
201*a3df083aSStefano Zampini }
202*a3df083aSStefano Zampini 
203*a3df083aSStefano Zampini /* used just in bddc debug mode */
204*a3df083aSStefano Zampini #undef __FUNCT__
205*a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
206*a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
207*a3df083aSStefano Zampini {
208*a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
209*a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
210*a3df083aSStefano Zampini   Mat            An;
211*a3df083aSStefano Zampini   PetscErrorCode ierr;
212*a3df083aSStefano Zampini 
213*a3df083aSStefano Zampini   PetscFunctionBegin;
214*a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
215*a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
216*a3df083aSStefano Zampini   if (is1) {
217*a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
218*a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
219*a3df083aSStefano Zampini   } else {
220*a3df083aSStefano Zampini     *B = An;
221*a3df083aSStefano Zampini   }
222*a3df083aSStefano Zampini   PetscFunctionReturn(0);
223*a3df083aSStefano Zampini }
224*a3df083aSStefano Zampini 
2251cf9b237SStefano Zampini /* TODO: add reuse flag */
2261cf9b237SStefano Zampini #undef __FUNCT__
2271cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
2281cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
2291cf9b237SStefano Zampini {
2301cf9b237SStefano Zampini   Mat            Bt;
2311cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
2321cf9b237SStefano Zampini   const PetscInt *ii,*ij;
2331cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
2341cf9b237SStefano Zampini   PetscBool      flg_row;
2351cf9b237SStefano Zampini   PetscErrorCode ierr;
2361cf9b237SStefano Zampini 
2371cf9b237SStefano Zampini   PetscFunctionBegin;
2381cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
2391cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
2401cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
2411cf9b237SStefano Zampini   nnz = n;
2421cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
2431cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
2441cf9b237SStefano Zampini   }
2451cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
2461cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
2471cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
2481cf9b237SStefano Zampini   nnz = 0;
2491cf9b237SStefano Zampini   bii[0] = 0;
2501cf9b237SStefano Zampini   for (i=0;i<n;i++) {
2511cf9b237SStefano Zampini     PetscInt j;
2521cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
2531cf9b237SStefano Zampini       PetscScalar entry = a[j];
2541cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
2551cf9b237SStefano Zampini         bij[nnz] = ij[j];
2561cf9b237SStefano Zampini         bdata[nnz] = entry;
2571cf9b237SStefano Zampini         nnz++;
2581cf9b237SStefano Zampini       }
2591cf9b237SStefano Zampini     }
2601cf9b237SStefano Zampini     bii[i+1] = nnz;
2611cf9b237SStefano Zampini   }
2621cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
2631cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
2641cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
2651cf9b237SStefano Zampini   {
2661cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
2671cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
2681cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
2691cf9b237SStefano Zampini   }
2701cf9b237SStefano Zampini   *B = Bt;
2711cf9b237SStefano Zampini   PetscFunctionReturn(0);
2721cf9b237SStefano Zampini }
2731cf9b237SStefano Zampini 
274674ae819SStefano Zampini #undef __FUNCT__
2754f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
2764f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
2774f1b2e48SStefano Zampini {
2784f1b2e48SStefano Zampini   Mat                    B;
2794f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
2804f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
2814f1b2e48SStefano Zampini   PCBDDCGraph            graph;
2824f1b2e48SStefano Zampini   PetscInt               i,n;
2834f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
2844f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
2854f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
2864f1b2e48SStefano Zampini   PetscErrorCode         ierr;
2874f1b2e48SStefano Zampini 
2884f1b2e48SStefano Zampini   PetscFunctionBegin;
2894f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
2904f1b2e48SStefano Zampini   if (!isseqaij && filter) {
2911cf9b237SStefano Zampini     PetscBool isseqdense;
2921cf9b237SStefano Zampini 
2931cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
2941cf9b237SStefano Zampini     if (!isseqdense) {
2954f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
2961cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
2971cf9b237SStefano Zampini       PetscScalar *array;
2981cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
2991cf9b237SStefano Zampini 
3001cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
3011cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
3021cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
3031cf9b237SStefano Zampini       for (i=0;i<n;i++) {
3041cf9b237SStefano Zampini         PetscInt j;
3051cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
3061cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
3071cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
3081cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
3091cf9b237SStefano Zampini         }
3101cf9b237SStefano Zampini       }
3111cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
3121cf9b237SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_REUSE_MATRIX,&B);CHKERRQ(ierr);
3131cf9b237SStefano Zampini     }
3144f1b2e48SStefano Zampini   } else {
3154f1b2e48SStefano Zampini     B = A;
3164f1b2e48SStefano Zampini   }
3174f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3184f1b2e48SStefano Zampini 
3194f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
3204f1b2e48SStefano Zampini   if (filter) {
3214f1b2e48SStefano Zampini     PetscScalar *data;
3224f1b2e48SStefano Zampini     PetscInt    j,cum;
3234f1b2e48SStefano Zampini 
3244f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
3254f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
3264f1b2e48SStefano Zampini     cum = 0;
3274f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
3284f1b2e48SStefano Zampini       PetscInt t;
3294f1b2e48SStefano Zampini 
3304f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
3314f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
3324f1b2e48SStefano Zampini           continue;
3334f1b2e48SStefano Zampini         }
3344f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
3354f1b2e48SStefano Zampini       }
3364f1b2e48SStefano Zampini       t = xadj_filtered[i];
3374f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
3384f1b2e48SStefano Zampini       cum += t;
3394f1b2e48SStefano Zampini     }
3404f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
3414f1b2e48SStefano Zampini   } else {
3424f1b2e48SStefano Zampini     xadj_filtered = NULL;
3434f1b2e48SStefano Zampini     adjncy_filtered = NULL;
3444f1b2e48SStefano Zampini   }
3454f1b2e48SStefano Zampini 
3464f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
3474f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
3484f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
3494f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3504f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
3514f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
3524f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3534f1b2e48SStefano Zampini   if (xadj_filtered) {
3544f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
3554f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
3564f1b2e48SStefano Zampini   } else {
3574f1b2e48SStefano Zampini     graph->xadj = xadj;
3584f1b2e48SStefano Zampini     graph->adjncy = adjncy;
3594f1b2e48SStefano Zampini   }
3604f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
3614f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3624f1b2e48SStefano Zampini   /* partial clean up */
3634f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
3644f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3651cf9b237SStefano Zampini   if (A != B) {
3664f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
3674f1b2e48SStefano Zampini   }
3684f1b2e48SStefano Zampini 
3694f1b2e48SStefano Zampini   /* get back data */
3701cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
3711cf9b237SStefano Zampini   if (cc) {
3724f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
3734f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
3744f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,graph->cptr[i+1]-graph->cptr[i],graph->queue+graph->cptr[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
3754f1b2e48SStefano Zampini     }
3764f1b2e48SStefano Zampini     *cc = cc_n;
3771cf9b237SStefano Zampini   }
3784f1b2e48SStefano Zampini   /* clean up graph */
3794f1b2e48SStefano Zampini   graph->xadj = 0;
3804f1b2e48SStefano Zampini   graph->adjncy = 0;
3814f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
3824f1b2e48SStefano Zampini   PetscFunctionReturn(0);
3834f1b2e48SStefano Zampini }
3844f1b2e48SStefano Zampini 
3854f1b2e48SStefano Zampini #undef __FUNCT__
3865408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
3875408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
3885408967cSStefano Zampini {
3895408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3905408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
391dee84bffSStefano Zampini   IS             dirIS = NULL;
3924f1b2e48SStefano Zampini   PetscInt       i;
3935408967cSStefano Zampini   PetscErrorCode ierr;
3945408967cSStefano Zampini 
3955408967cSStefano Zampini   PetscFunctionBegin;
396dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
3975408967cSStefano Zampini   if (zerodiag) {
3985408967cSStefano Zampini     Mat            A;
3995408967cSStefano Zampini     Vec            vec3_N;
4005408967cSStefano Zampini     PetscScalar    *vals;
4015408967cSStefano Zampini     const PetscInt *idxs;
4024f1b2e48SStefano Zampini     PetscInt       nz;
4035408967cSStefano Zampini 
4045408967cSStefano Zampini     /* p0 */
4055408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
4065408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
4075408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
4085408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
4094f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
4105408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4115408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4125408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4135408967cSStefano Zampini     /* v_I */
4145408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
4155408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
4165408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4175408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
4185408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
4195408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
4205408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4215408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
4225408967cSStefano Zampini     if (dirIS) {
4235408967cSStefano Zampini       PetscInt n;
4245408967cSStefano Zampini 
4255408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
4265408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
4275408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
4285408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4295408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
4305408967cSStefano Zampini     }
4315408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
4325408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
4335408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
4345408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
4355408967cSStefano Zampini     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
4365408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
4375408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
4384f1b2e48SStefano Zampini     if (PetscAbsScalar(vals[0]) > PETSC_SMALL) {
4395408967cSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! b(v_I,p_0) = %f (should be numerically 0.)",PetscAbsScalar(vals[0]));
4405408967cSStefano Zampini     }
4415408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
4425408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
4435408967cSStefano Zampini   }
444dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
4455408967cSStefano Zampini 
4465408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
4475408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
4484f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
4495408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
4504f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
4515408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
4524f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
4534f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
4544f1b2e48SStefano Zampini       SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %1.4e at %d instead of %1.4e\n",pcbddc->benign_p0[i],i,-PetscGlobalRank-i);CHKERRQ(ierr);
4554f1b2e48SStefano Zampini     }
4565408967cSStefano Zampini   }
4575408967cSStefano Zampini   PetscFunctionReturn(0);
4585408967cSStefano Zampini }
4595408967cSStefano Zampini 
4605408967cSStefano Zampini #undef __FUNCT__
461339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
462339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
463339f8db1SStefano Zampini {
464339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4654f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
466b0f5fe93SStefano Zampini   PetscInt       nz,n;
4674f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
468339f8db1SStefano Zampini   PetscErrorCode ierr;
469339f8db1SStefano Zampini 
470339f8db1SStefano Zampini   PetscFunctionBegin;
4719f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
4729f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
473339f8db1SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
474*a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
475*a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
476*a3df083aSStefano Zampini   }
477*a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
478*a3df083aSStefano Zampini   pcbddc->benign_n = 0;
4794f1b2e48SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
4804f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
4814f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
4824f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
4834f1b2e48SStefano Zampini      since the local Schur complements are SPD
4844f1b2e48SStefano Zampini   */
4854f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
4864f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
48740fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
4884f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
4894f1b2e48SStefano Zampini 
4904f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
4914f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
4924f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
4934f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
494ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
49540fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
49640fa8d13SStefano Zampini     if (!sorted) {
49740fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
49840fa8d13SStefano Zampini     }
49940fa8d13SStefano Zampini   } else {
50040fa8d13SStefano Zampini     pressures = NULL;
50140fa8d13SStefano Zampini   }
50297d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
50397d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
5044f1b2e48SStefano Zampini   /* TODO: add check for shared dofs and raise error */
50597d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
506339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
507339f8db1SStefano Zampini   if (!sorted) {
508339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
509339f8db1SStefano Zampini   }
510339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5114f1b2e48SStefano Zampini   if (!nz) {
5124f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
5134f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
51440fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
51540fa8d13SStefano Zampini   }
5164f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
5174f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
5184f1b2e48SStefano Zampini   zerodiag_subs = NULL;
5194f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
5204f1b2e48SStefano Zampini   if (has_null_pressures) {
5214f1b2e48SStefano Zampini     IS       *subs;
5224f1b2e48SStefano Zampini     PetscInt nsubs,i;
5234f1b2e48SStefano Zampini 
5244f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
5254f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
5264f1b2e48SStefano Zampini     if (nsubs > 1) {
5274f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
5284f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
5294f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
5304f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
5314f1b2e48SStefano Zampini         PetscInt               nl;
5324f1b2e48SStefano Zampini 
5334f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
5344f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
5354f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
5364f1b2e48SStefano Zampini         if (nl) {
5374f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
5384f1b2e48SStefano Zampini 
5394f1b2e48SStefano Zampini           if (pressures) {
5404f1b2e48SStefano Zampini             IS t_pressure_subs;
5414f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
5424f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
5434f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
5444f1b2e48SStefano Zampini           }
5454f1b2e48SStefano Zampini           if (valid) {
5464f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
5474f1b2e48SStefano Zampini             pcbddc->benign_n++;
5484f1b2e48SStefano Zampini           } else {
5494f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
5504f1b2e48SStefano Zampini           }
5514f1b2e48SStefano Zampini         }
5524f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
5534f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
5544f1b2e48SStefano Zampini       }
5554f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
5564f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
5574f1b2e48SStefano Zampini       if (pressures) {
5584f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
5594f1b2e48SStefano Zampini       }
5604f1b2e48SStefano Zampini       if (valid) {
5614f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
562ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
5634f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
5644f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
5654f1b2e48SStefano Zampini       }
5664f1b2e48SStefano Zampini     }
5674f1b2e48SStefano Zampini   }
5684f1b2e48SStefano Zampini 
5694f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
5704f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
5714f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
5724f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
5734f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
5744f1b2e48SStefano Zampini   }
5754f1b2e48SStefano Zampini 
5764f1b2e48SStefano Zampini   /* final check for null pressures */
5774f1b2e48SStefano Zampini   if (zerodiag && pressures) {
5784f1b2e48SStefano Zampini     PetscInt nz,np;
5794f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5804f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
5814f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
5824f1b2e48SStefano Zampini   }
5834f1b2e48SStefano Zampini 
5844f1b2e48SStefano Zampini   if (recompute_zerodiag) {
5854f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
5864f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
5874f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
5884f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
5894f1b2e48SStefano Zampini     } else {
5904f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
5914f1b2e48SStefano Zampini 
5924f1b2e48SStefano Zampini       nzn = 0;
5934f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
5944f1b2e48SStefano Zampini         PetscInt ns;
5954f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
5964f1b2e48SStefano Zampini         nzn += ns;
5974f1b2e48SStefano Zampini       }
5984f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
5994f1b2e48SStefano Zampini       nzn = 0;
6004f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
6014f1b2e48SStefano Zampini         PetscInt ns,*idxs;
6024f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
6034f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
6044f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
6054f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
6064f1b2e48SStefano Zampini         nzn += ns;
6074f1b2e48SStefano Zampini       }
6084f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
6094f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
6104f1b2e48SStefano Zampini     }
6114f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
6124f1b2e48SStefano Zampini   }
6134f1b2e48SStefano Zampini 
6144f1b2e48SStefano Zampini   if (has_null_pressures) {
6154f1b2e48SStefano Zampini     IS             zerodiagc;
6164f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
6174f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
6184f1b2e48SStefano Zampini 
6194f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
620339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
621339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
622339f8db1SStefano Zampini     /* local change of basis for pressures */
623339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
62497d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
625339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
626339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
627339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
6284f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
6294f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
6304f1b2e48SStefano Zampini       PetscInt nzs,j;
6314f1b2e48SStefano Zampini 
6324f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
6334f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
6344f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
6354f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
6364f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
6374f1b2e48SStefano Zampini     }
638339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
639339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
640339f8db1SStefano Zampini     /* set identity on velocities */
641339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
642339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
643339f8db1SStefano Zampini     }
6444f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
6454f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
6469f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
6474f1b2e48SStefano Zampini     ierr = PetscMalloc3(pcbddc->benign_n,&pcbddc->benign_p0_lidx,pcbddc->benign_n,&pcbddc->benign_p0_gidx,pcbddc->benign_n,&pcbddc->benign_p0);CHKERRQ(ierr);
648339f8db1SStefano Zampini     /* set change on pressures */
6494f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
6504f1b2e48SStefano Zampini       PetscScalar *array;
6514f1b2e48SStefano Zampini       PetscInt    nzs;
6524f1b2e48SStefano Zampini 
6534f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
6544f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
6554f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
656339f8db1SStefano Zampini         PetscScalar vals[2];
657339f8db1SStefano Zampini         PetscInt    cols[2];
658339f8db1SStefano Zampini 
659339f8db1SStefano Zampini         cols[0] = idxs[i];
6604f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
661339f8db1SStefano Zampini         vals[0] = 1.;
662b0f5fe93SStefano Zampini         vals[1] = 1.;
6634f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
664339f8db1SStefano Zampini       }
6654f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
6664f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
6674f1b2e48SStefano Zampini       array[nzs-1] = 1.;
6684f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
6694f1b2e48SStefano Zampini       /* store local idxs for p0 */
6704f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
6714f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
672339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
6734f1b2e48SStefano Zampini     }
674339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
675339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
676*a3df083aSStefano Zampini     /* project if needed */
677*a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
67897d764eeSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&pcbddc->benign_original_mat);CHKERRQ(ierr);
679339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
68097d764eeSStefano Zampini       ierr = MatSeqAIJCompress(pcbddc->benign_original_mat,&pcbddc->local_mat);CHKERRQ(ierr);
68197d764eeSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
682*a3df083aSStefano Zampini     }
6834f1b2e48SStefano Zampini     /* store global idxs for p0 */
6844f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
685339f8db1SStefano Zampini   }
686ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
6874f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
688b0f5fe93SStefano Zampini 
689b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
690b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
691339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
692339f8db1SStefano Zampini   PetscFunctionReturn(0);
693339f8db1SStefano Zampini }
694339f8db1SStefano Zampini 
695339f8db1SStefano Zampini #undef __FUNCT__
696015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
697015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
698efc2fbd9SStefano Zampini {
699efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
700efc2fbd9SStefano Zampini   PetscErrorCode ierr;
701efc2fbd9SStefano Zampini 
702efc2fbd9SStefano Zampini   PetscFunctionBegin;
703efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
704efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
7054f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
706efc2fbd9SStefano Zampini   }
707015636ebSStefano Zampini   if (get) { /* use SF to get values */
708efc2fbd9SStefano Zampini     PetscScalar *array;
709efc2fbd9SStefano Zampini 
710efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
7114f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
7124f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
713efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
7144f1b2e48SStefano Zampini   } else { /* use VecSetValues (not scalable, I should try to find a better solution (defining a new MPI_OP for reduction) */
7154f1b2e48SStefano Zampini     ierr = VecSetValues(v,pcbddc->benign_n,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
716efc2fbd9SStefano Zampini     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
717efc2fbd9SStefano Zampini     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
718efc2fbd9SStefano Zampini   }
719efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
720efc2fbd9SStefano Zampini }
721efc2fbd9SStefano Zampini 
722efc2fbd9SStefano Zampini #undef __FUNCT__
723c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
724c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
725c263805aSStefano Zampini {
726c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
727c263805aSStefano Zampini   PetscErrorCode ierr;
728c263805aSStefano Zampini 
729c263805aSStefano Zampini   PetscFunctionBegin;
730c263805aSStefano Zampini   /* TODO: add error checking
731c263805aSStefano Zampini     - avoid nested pop (or push) calls.
732c263805aSStefano Zampini     - cannot push before pop.
7331c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
734c263805aSStefano Zampini   */
7354f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
736efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
737efc2fbd9SStefano Zampini   }
738c263805aSStefano Zampini   if (pop) {
739*a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
7404f1b2e48SStefano Zampini       IS       is_p0;
7414f1b2e48SStefano Zampini       MatReuse reuse;
742c263805aSStefano Zampini 
743c263805aSStefano Zampini       /* extract B_0 */
7444f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
7454f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
7464f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
7474f1b2e48SStefano Zampini       }
7484f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
7494f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
750c263805aSStefano Zampini       /* remove rows and cols from local problem */
751c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
75297d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7534f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
7544f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
755*a3df083aSStefano Zampini     } else {
756*a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
757*a3df083aSStefano Zampini       PetscScalar *vals;
758*a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
759*a3df083aSStefano Zampini 
760*a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
761*a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
762*a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
763*a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
764*a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
765*a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
766*a3df083aSStefano Zampini         /* this matrix is very sparse: the nnz pattern is not known unless we do 2 sweeps of the next loop.
767*a3df083aSStefano Zampini            Setting nnz=100 should be more than enough */
768*a3df083aSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,100,NULL);CHKERRQ(ierr);
769*a3df083aSStefano Zampini       }
770*a3df083aSStefano Zampini 
771*a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
772*a3df083aSStefano Zampini         PetscScalar *array;
773*a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
774*a3df083aSStefano Zampini 
775*a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
776*a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
777*a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
778*a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
779*a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
780*a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
781*a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
782*a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
783*a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
784*a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
785*a3df083aSStefano Zampini         cum = 0;
786*a3df083aSStefano Zampini         for (j=0;j<n;j++) {
787*a3df083aSStefano Zampini           if (PetscUnlikely(PetscAbsReal(array[j]) > PETSC_SMALL)) {
788*a3df083aSStefano Zampini             vals[cum] = array[j];
789*a3df083aSStefano Zampini             idxs_ins[cum] = j;
790*a3df083aSStefano Zampini             cum++;
791*a3df083aSStefano Zampini           }
792*a3df083aSStefano Zampini         }
793*a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
794*a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
795*a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
796*a3df083aSStefano Zampini       }
797*a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
798*a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
799*a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
800*a3df083aSStefano Zampini     }
801c263805aSStefano Zampini   } else { /* push */
802*a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
8034f1b2e48SStefano Zampini       PetscInt i;
8044f1b2e48SStefano Zampini 
8054f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
8064f1b2e48SStefano Zampini         PetscScalar *B0_vals;
8074f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
8084f1b2e48SStefano Zampini 
8094f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
8104f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
8117b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
8124f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
8134f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
8144f1b2e48SStefano Zampini       }
815c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
816c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
817*a3df083aSStefano Zampini     } else {
818*a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
819*a3df083aSStefano Zampini     }
820c263805aSStefano Zampini   }
821c263805aSStefano Zampini   PetscFunctionReturn(0);
822c263805aSStefano Zampini }
823c263805aSStefano Zampini 
824c263805aSStefano Zampini #undef __FUNCT__
825b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
82608122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
827b1b3d7a2SStefano Zampini {
828b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
82908122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
83008122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
83108122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
83208122e43SStefano Zampini   PetscScalar     *work,lwork;
83308122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
83408122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
83508122e43SStefano Zampini   PetscReal       *eigs,thresh;
8361b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
837f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
83808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
83908122e43SStefano Zampini   PetscReal       *rwork;
84008122e43SStefano Zampini #endif
841b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
842b1b3d7a2SStefano Zampini 
843b1b3d7a2SStefano Zampini   PetscFunctionBegin;
84408122e43SStefano Zampini   if (!sub_schurs->use_mumps) {
84508122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
84608122e43SStefano Zampini   }
84708122e43SStefano Zampini 
84806a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
84906a4e24aSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adaptive selection not yet implemented for general matrix pencils (herm %d, posdef %d)\n",sub_schurs->is_hermitian,sub_schurs->is_posdef);
85006a4e24aSStefano Zampini   }
85106a4e24aSStefano Zampini 
852fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
853fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
854fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
855fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
8561575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
857fd14bc51SStefano Zampini   }
858fd14bc51SStefano Zampini 
859e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
860e496cd5dSStefano Zampini     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %d (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef);
861e496cd5dSStefano Zampini   }
862e496cd5dSStefano Zampini 
86308122e43SStefano Zampini   /* max size of subsets */
86408122e43SStefano Zampini   mss = 0;
86508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
86608122e43SStefano Zampini     PetscInt subset_size;
867862806e4SStefano Zampini 
86808122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
86908122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
87008122e43SStefano Zampini   }
87108122e43SStefano Zampini 
87208122e43SStefano Zampini   /* min/max and threshold */
87308122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
874f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
87508122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
876f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
877f6f667cfSStefano Zampini   if (nmin) {
878f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
879f6f667cfSStefano Zampini   }
88008122e43SStefano Zampini 
88108122e43SStefano Zampini   /* allocate lapack workspace */
88208122e43SStefano Zampini   cum = cum2 = 0;
88308122e43SStefano Zampini   maxneigs = 0;
88408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
88508122e43SStefano Zampini     PetscInt n,subset_size;
886f6f667cfSStefano Zampini 
88708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
88808122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
8899162d606SStefano Zampini     cum += subset_size;
8909162d606SStefano Zampini     cum2 += subset_size*n;
89108122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
89208122e43SStefano Zampini   }
89308122e43SStefano Zampini   if (mss) {
8949ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
89508122e43SStefano Zampini       PetscBLASInt B_itype = 1;
89608122e43SStefano Zampini       PetscBLASInt B_N = mss;
8974c6709b3SStefano Zampini       PetscReal    zero = 0.0;
8984c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
89908122e43SStefano Zampini 
90008122e43SStefano Zampini       B_lwork = -1;
90108122e43SStefano Zampini       S = NULL;
90208122e43SStefano Zampini       St = NULL;
903a58a30b4SStefano Zampini       eigs = NULL;
904a58a30b4SStefano Zampini       eigv = NULL;
905a58a30b4SStefano Zampini       B_iwork = NULL;
906a58a30b4SStefano Zampini       B_ifail = NULL;
907d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
908d1710679SStefano Zampini       rwork = NULL;
909d1710679SStefano Zampini #endif
9108bec7fa6SStefano Zampini       thresh = 1.0;
91108122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
91208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
91308122e43SStefano 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));
91408122e43SStefano Zampini #else
91508122e43SStefano 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));
91608122e43SStefano Zampini #endif
91708122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
91808122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
91908122e43SStefano Zampini     } else {
92008122e43SStefano Zampini         /* TODO */
92108122e43SStefano Zampini     }
92208122e43SStefano Zampini   } else {
92308122e43SStefano Zampini     lwork = 0;
92408122e43SStefano Zampini   }
92508122e43SStefano Zampini 
92608122e43SStefano Zampini   nv = 0;
927d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) { /* complement set of active subsets, each entry is a vertex (boundary made by active subsets, vertices and dirichlet dofs) */
928d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
92908122e43SStefano Zampini   }
9304c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
931f6f667cfSStefano Zampini   if (allocated_S_St) {
932f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
933f6f667cfSStefano Zampini   }
934f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
93508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
93608122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
93708122e43SStefano Zampini #endif
9389162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
9399162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
9409162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
94108122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
9429162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
94308122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
94408122e43SStefano Zampini 
94508122e43SStefano Zampini   maxneigs = 0;
94608122e43SStefano Zampini   cum = cum2 = cumarray = 0;
9479162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
9489162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
949d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
95008122e43SStefano Zampini     const PetscInt *idxs;
95108122e43SStefano Zampini 
952d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
95308122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
95408122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
95508122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
95608122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
9579162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
9589162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
95908122e43SStefano Zampini     }
96008122e43SStefano Zampini     cum2 = cum;
961d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
96208122e43SStefano Zampini   }
96308122e43SStefano Zampini 
96408122e43SStefano Zampini   if (mss) { /* multilevel */
96508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
96608122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
96708122e43SStefano Zampini   }
96808122e43SStefano Zampini 
969ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
97008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
97108122e43SStefano Zampini     const PetscInt *idxs;
972f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
973862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
97408122e43SStefano Zampini     PetscBLASInt   B_N;
975aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
97608122e43SStefano Zampini 
977862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
978ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
979f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
980f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
9819ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
982aff50787SStefano Zampini         PetscInt j,k;
983aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
984aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
985aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
98608122e43SStefano Zampini         }
98708122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
988aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
989aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
990aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
991aff50787SStefano Zampini           }
99208122e43SStefano Zampini         }
99308122e43SStefano Zampini       } else {
99408122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
99508122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
99608122e43SStefano Zampini       }
9978bec7fa6SStefano Zampini     } else {
998f6f667cfSStefano Zampini       S = Sarray + cumarray;
999f6f667cfSStefano Zampini       St = Starray + cumarray;
10008bec7fa6SStefano Zampini     }
100108122e43SStefano Zampini 
1002aff50787SStefano Zampini     /* see if we can save some work */
1003aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
1004aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1005aff50787SStefano Zampini     }
1006aff50787SStefano Zampini 
1007aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
1008aff50787SStefano Zampini       B_neigs = 0;
1009aff50787SStefano Zampini     } else {
10109ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
101108122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1012f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
10134c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
10149552c7c7SStefano Zampini         PetscInt     nmin_s;
101508122e43SStefano Zampini 
1016fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
10178bec7fa6SStefano Zampini           PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %d/%d %d %d.\n",i,sub_schurs->n_subs,subset_size,pcbddc->mat_graph->count[idxs[0]]);
1018fd14bc51SStefano Zampini         }
1019d16cbb6bSStefano Zampini 
102008122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1021d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
1022d16cbb6bSStefano Zampini 
1023d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
102408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1025f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
102608122e43SStefano Zampini #else
1027f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
102808122e43SStefano Zampini #endif
1029d16cbb6bSStefano Zampini         } else {
1030d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1031d16cbb6bSStefano Zampini           B_IL = 1;
1032d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1033d16cbb6bSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
1034d16cbb6bSStefano Zampini #else
1035d16cbb6bSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
1036d16cbb6bSStefano Zampini #endif
1037d16cbb6bSStefano Zampini         }
103808122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
103908122e43SStefano Zampini         if (B_ierr) {
104008122e43SStefano Zampini           if (B_ierr < 0 ) {
104108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
104208122e43SStefano Zampini           } else if (B_ierr <= B_N) {
104308122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
104408122e43SStefano Zampini           } else {
10459552c7c7SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1);
104608122e43SStefano Zampini           }
104708122e43SStefano Zampini         }
104808122e43SStefano Zampini 
104908122e43SStefano Zampini         if (B_neigs > nmax) {
1050fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1051fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1052fd14bc51SStefano Zampini           }
1053f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
105408122e43SStefano Zampini           B_neigs = nmax;
105508122e43SStefano Zampini         }
105608122e43SStefano Zampini 
10579552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
10589552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
105908122e43SStefano Zampini           PetscBLASInt B_neigs2;
106008122e43SStefano Zampini 
1061f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
1062f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
1063fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1064fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, less than minimum required %d. Asking for %d to %d incl (fortran like)\n",B_neigs,nmin,B_IL,B_IU);
1065fd14bc51SStefano Zampini           }
10669ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
106708122e43SStefano Zampini             PetscInt j;
106808122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
106908122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
107008122e43SStefano Zampini             }
107108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
107208122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
107308122e43SStefano Zampini             }
107408122e43SStefano Zampini           } else {
107508122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
107608122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
107708122e43SStefano Zampini           }
107808122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
107908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1080f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
108108122e43SStefano Zampini #else
1082f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
108308122e43SStefano Zampini #endif
108408122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
108508122e43SStefano Zampini           B_neigs += B_neigs2;
108608122e43SStefano Zampini         }
108708122e43SStefano Zampini         if (B_ierr) {
108808122e43SStefano Zampini           if (B_ierr < 0 ) {
108908122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
109008122e43SStefano Zampini           } else if (B_ierr <= B_N) {
109108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
109208122e43SStefano Zampini           } else {
10939552c7c7SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1);
109408122e43SStefano Zampini           }
109508122e43SStefano Zampini         }
1096fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1097ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
109808122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
109908122e43SStefano Zampini             if (eigs[j] == 0.0) {
1100ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
110108122e43SStefano Zampini             } else {
1102ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
1103fd14bc51SStefano Zampini             }
110408122e43SStefano Zampini           }
110508122e43SStefano Zampini         }
110608122e43SStefano Zampini       } else {
110708122e43SStefano Zampini           /* TODO */
110808122e43SStefano Zampini       }
1109aff50787SStefano Zampini     }
11108bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
11118bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
11129162d606SStefano Zampini     if (B_neigs) {
11139162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1114fd14bc51SStefano Zampini 
1115fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
11169552c7c7SStefano Zampini         PetscInt ii;
11179552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1118ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
11199552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1120ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1121ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1122ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1123ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1124ac47001eSStefano Zampini #else
1125ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);CHKERRQ(ierr);
1126ac47001eSStefano Zampini #endif
11279552c7c7SStefano Zampini           }
11289552c7c7SStefano Zampini         }
1129fd14bc51SStefano Zampini       }
113008122e43SStefano Zampini #if 0
11319162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
113208122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
113308122e43SStefano Zampini         PetscScalar norm;
113408122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
11359162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
11369162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
113708122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
113808122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
113908122e43SStefano Zampini         } else {
114008122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
114108122e43SStefano Zampini         }
11429162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
1143b1b3d7a2SStefano Zampini       }
1144b1b3d7a2SStefano Zampini #endif
11459162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
11469162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
11479162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
11489162d606SStefano Zampini       cum++;
114908122e43SStefano Zampini     }
115008122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
115108122e43SStefano Zampini     /* shift for next computation */
115208122e43SStefano Zampini     cumarray += subset_size*subset_size;
115308122e43SStefano Zampini   }
1154fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1155fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1156fd14bc51SStefano Zampini   }
115708122e43SStefano Zampini 
115808122e43SStefano Zampini   if (mss) {
115908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
116008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1161f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1162f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1163f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
116408122e43SStefano Zampini   }
1165f6f667cfSStefano Zampini   if (allocated_S_St) {
1166f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1167f6f667cfSStefano Zampini   }
1168f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
116908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
117008122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
117108122e43SStefano Zampini #endif
117208122e43SStefano Zampini   if (pcbddc->dbg_flag) {
11731b968477SStefano Zampini     PetscInt maxneigs_r;
117408122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
11759b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
117608122e43SStefano Zampini   }
117708122e43SStefano Zampini   PetscFunctionReturn(0);
117808122e43SStefano Zampini }
1179b1b3d7a2SStefano Zampini 
1180674ae819SStefano Zampini #undef __FUNCT__
1181c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1182c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1183c8587f34SStefano Zampini {
1184c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
11858629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1186c8587f34SStefano Zampini   PetscErrorCode ierr;
1187c8587f34SStefano Zampini 
1188c8587f34SStefano Zampini   PetscFunctionBegin;
1189f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
11905e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1191c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1192c8587f34SStefano Zampini 
1193684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
11940fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1195684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1196c8587f34SStefano Zampini 
1197c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1198b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
1199c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1200c8587f34SStefano Zampini   }
1201c8587f34SStefano Zampini 
12028629588bSStefano Zampini   /*
12038629588bSStefano Zampini      Setup local correction and local part of coarse basis.
12048629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
12058629588bSStefano Zampini   */
120647f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
12078629588bSStefano Zampini 
12088629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
12098629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
12108629588bSStefano Zampini 
12118629588bSStefano Zampini   /* free */
12128629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1213c8587f34SStefano Zampini   PetscFunctionReturn(0);
1214c8587f34SStefano Zampini }
1215c8587f34SStefano Zampini 
1216c8587f34SStefano Zampini #undef __FUNCT__
1217674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1218674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1219674ae819SStefano Zampini {
1220674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1221674ae819SStefano Zampini   PetscErrorCode ierr;
1222674ae819SStefano Zampini 
1223674ae819SStefano Zampini   PetscFunctionBegin;
1224674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1225674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
122630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1227674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
1228674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1229785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1230674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1231f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1232f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1233785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
123463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
123563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1236674ae819SStefano Zampini   PetscFunctionReturn(0);
1237674ae819SStefano Zampini }
1238674ae819SStefano Zampini 
1239674ae819SStefano Zampini #undef __FUNCT__
1240674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1241674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1242674ae819SStefano Zampini {
1243674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12444f1b2e48SStefano Zampini   PetscInt       i;
1245674ae819SStefano Zampini   PetscErrorCode ierr;
1246674ae819SStefano Zampini 
1247674ae819SStefano Zampini   PetscFunctionBegin;
1248b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1249674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
1250674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1251674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
12524f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
12534f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
12544f1b2e48SStefano Zampini   }
12554f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1256b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1257674ae819SStefano Zampini   PetscFunctionReturn(0);
1258674ae819SStefano Zampini }
1259674ae819SStefano Zampini 
1260674ae819SStefano Zampini #undef __FUNCT__
1261674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1262674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1263674ae819SStefano Zampini {
1264674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1265674ae819SStefano Zampini   PetscErrorCode ierr;
1266674ae819SStefano Zampini 
1267674ae819SStefano Zampini   PetscFunctionBegin;
1268674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
126958da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1270ca92afb2SStefano Zampini     PetscScalar *array;
127106656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
127206656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
127358da7f69SStefano Zampini   }
1274674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1275674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
127615aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
127715aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1278674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1279674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1280674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
128106656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1282674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1283674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
12848ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1285674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1286674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1287674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1288f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1289f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1290f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1291f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1292727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
12930e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1294f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
129570cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
12966e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
129781d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
12980369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
12998b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
13004f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
13018b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1302ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1303ca92afb2SStefano Zampini     PetscInt i;
1304ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1305ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1306ca92afb2SStefano Zampini     }
1307ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1308ca92afb2SStefano Zampini   }
13094f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1310674ae819SStefano Zampini   PetscFunctionReturn(0);
1311674ae819SStefano Zampini }
1312674ae819SStefano Zampini 
1313674ae819SStefano Zampini #undef __FUNCT__
1314f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1315f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
13166bfb1811SStefano Zampini {
13176bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
13186bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
13196bfb1811SStefano Zampini   VecType        impVecType;
13204f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
13216bfb1811SStefano Zampini   PetscErrorCode ierr;
13226bfb1811SStefano Zampini 
13236bfb1811SStefano Zampini   PetscFunctionBegin;
1324f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
1325019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1326f4ddd8eeSStefano Zampini   }
1327e7b262bdSStefano Zampini   /* get sizes */
13284f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1329b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
13306bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1331e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1332e7b262bdSStefano Zampini   /* R nodes */
1333e7b262bdSStefano Zampini   old_size = -1;
1334e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1335e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1336e7b262bdSStefano Zampini   }
1337e7b262bdSStefano Zampini   if (n_R != old_size) {
1338e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1339e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
13406bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
13416bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
13426bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
13436bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1344e7b262bdSStefano Zampini   }
1345e7b262bdSStefano Zampini   /* local primal dofs */
1346e7b262bdSStefano Zampini   old_size = -1;
1347e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1348e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1349e7b262bdSStefano Zampini   }
1350e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1351e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
135283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1353e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
13546bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1355e7b262bdSStefano Zampini   }
1356e7b262bdSStefano Zampini   /* local explicit constraints */
1357e7b262bdSStefano Zampini   old_size = -1;
1358e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1359e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1360e7b262bdSStefano Zampini   }
1361e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1362e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
136383b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
136483b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
136583b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
136683b7ccabSStefano Zampini   }
13676bfb1811SStefano Zampini   PetscFunctionReturn(0);
13686bfb1811SStefano Zampini }
13696bfb1811SStefano Zampini 
13706bfb1811SStefano Zampini #undef __FUNCT__
137147f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
137247f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
137388ebb749SStefano Zampini {
137425084f0cSStefano Zampini   PetscErrorCode  ierr;
137525084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
137688ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
137788ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1378d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
137925084f0cSStefano Zampini   /* submatrices of local problem */
138080677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
1381019a44ceSStefano Zampini   /* submatrices of benign trick */
1382d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
138306656605SStefano Zampini   /* submatrices of local coarse problem */
138406656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
138525084f0cSStefano Zampini   /* working matrices */
138606656605SStefano Zampini   Mat             C_CR;
138725084f0cSStefano Zampini   /* additional working stuff */
138806656605SStefano Zampini   PC              pc_R;
13894f1b2e48SStefano Zampini   Mat             F;
1390*a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
139106656605SStefano Zampini 
139225084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
139306656605SStefano Zampini   PetscScalar     *work;
139406656605SStefano Zampini   PetscInt        *idx_V_B;
1395ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
139606656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1397ffd830a3SStefano Zampini 
139825084f0cSStefano Zampini   /* some shortcuts to scalars */
139906656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
140088ebb749SStefano Zampini 
140188ebb749SStefano Zampini   PetscFunctionBegin;
1402ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1403ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1404ffd830a3SStefano Zampini   }
1405ffd830a3SStefano Zampini 
1406ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1407b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
14084f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1409b371cd4fSStefano Zampini   n_B = pcis->n_B;
1410b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
141188ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
141288ebb749SStefano Zampini 
141388ebb749SStefano Zampini   /* vertices in boundary numbering */
1414785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
14150e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
141688ebb749SStefano Zampini   if (i != n_vertices) {
141722d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
141888ebb749SStefano Zampini   }
141988ebb749SStefano Zampini 
142006656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1421019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
142206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
142306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
142406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
142506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
142606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
142706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
142806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
142906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
143006656605SStefano Zampini 
143106656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
143206656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
143306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
143406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
143506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1436ffd830a3SStefano Zampini   lda_rhs = n_R;
1437*a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
143806656605SStefano Zampini   if (isLU || isILU || isCHOL) {
143906656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1440d62866d3SStefano Zampini   } else if (sub_schurs->reuse_mumps) {
1441d62866d3SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1442d62866d3SStefano Zampini     MatFactorType type;
1443d62866d3SStefano Zampini 
14446816873aSStefano Zampini     F = reuse_mumps->F;
14456816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1446d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1447ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
1448*a3df083aSStefano Zampini     need_benign_correction = !!reuse_mumps->benign_n;
144906656605SStefano Zampini   } else {
145006656605SStefano Zampini     F = NULL;
145106656605SStefano Zampini   }
145206656605SStefano Zampini 
1453ffd830a3SStefano Zampini   /* allocate workspace */
1454ffd830a3SStefano Zampini   n = 0;
1455ffd830a3SStefano Zampini   if (n_constraints) {
1456ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1457ffd830a3SStefano Zampini   }
1458ffd830a3SStefano Zampini   if (n_vertices) {
1459ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1460ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1461ffd830a3SStefano Zampini   }
1462ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1463ffd830a3SStefano Zampini 
146488ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
146588ebb749SStefano Zampini   if (n_constraints) {
146606656605SStefano Zampini     Mat         M1,M2,M3;
146780677318SStefano Zampini     Mat         auxmat;
146806656605SStefano Zampini     IS          is_aux;
146980677318SStefano Zampini     PetscScalar *array,*array2;
147006656605SStefano Zampini 
1471f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
147280677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
147388ebb749SStefano Zampini 
147425084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
147525084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
14768ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
147780677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
147888ebb749SStefano Zampini 
147980677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
148080677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1481ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
148288ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
148306656605SStefano Zampini       const PetscScalar *row_cmat_values;
148406656605SStefano Zampini       const PetscInt    *row_cmat_indices;
148506656605SStefano Zampini       PetscInt          size_of_constraint,j;
148688ebb749SStefano Zampini 
148706656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
148806656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1489ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
149006656605SStefano Zampini       }
149106656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
149206656605SStefano Zampini     }
1493ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
149406656605SStefano Zampini     if (F) {
149506656605SStefano Zampini       Mat B;
149606656605SStefano Zampini 
1497ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1498*a3df083aSStefano Zampini       if (need_benign_correction) {
1499*a3df083aSStefano Zampini         PetscScalar      *marr;
1500*a3df083aSStefano Zampini         PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1501*a3df083aSStefano Zampini 
1502*a3df083aSStefano Zampini         ierr = MatDenseGetArray(B,&marr);CHKERRQ(ierr);
1503*a3df083aSStefano Zampini         for (i=0;i<n_constraints;i++) {
1504*a3df083aSStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1505*a3df083aSStefano Zampini           ierr = PCBDDCReuseSolversChangeInterior(reuse_mumps,pcbddc->vec1_R,NULL,PETSC_FALSE);CHKERRQ(ierr);
1506*a3df083aSStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1507*a3df083aSStefano Zampini         }
1508*a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(B,&marr);CHKERRQ(ierr);
1509*a3df083aSStefano Zampini       }
151080677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1511*a3df083aSStefano Zampini       if (need_benign_correction) {
1512*a3df083aSStefano Zampini         PetscScalar      *marr;
1513*a3df083aSStefano Zampini         PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1514*a3df083aSStefano Zampini 
1515*a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1516*a3df083aSStefano Zampini         for (i=0;i<n_constraints;i++) {
1517*a3df083aSStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1518*a3df083aSStefano Zampini           ierr = PCBDDCReuseSolversChangeInterior(reuse_mumps,pcbddc->vec1_R,NULL,PETSC_TRUE);CHKERRQ(ierr);
1519*a3df083aSStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1520*a3df083aSStefano Zampini         }
1521*a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1522*a3df083aSStefano Zampini       }
152306656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
152406656605SStefano Zampini     } else {
152580677318SStefano Zampini       PetscScalar *marr;
152680677318SStefano Zampini 
152780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
152806656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1529ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1530ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
153106656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
153206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
153306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
153406656605SStefano Zampini       }
153580677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
153606656605SStefano Zampini     }
153780677318SStefano Zampini     if (!pcbddc->switch_static) {
153880677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
153980677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
154080677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
154180677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1542ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
154380677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
154480677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
154580677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
154680677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
154780677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
154880677318SStefano Zampini       }
154980677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
155080677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
155180677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
155280677318SStefano Zampini     } else {
1553ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1554ffd830a3SStefano Zampini         IS dummy;
1555ffd830a3SStefano Zampini 
1556ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
1557ffd830a3SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,dummy,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1558ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1559ffd830a3SStefano Zampini       } else {
156080677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
156180677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1562ffd830a3SStefano Zampini       }
156325084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
156480677318SStefano Zampini     }
156580677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
156680677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
156780677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
156806656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
156906656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
157080677318SStefano Zampini     if (isCHOL) {
157180677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
157280677318SStefano Zampini     } else {
157325084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
157480677318SStefano Zampini     }
157580677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
157606656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
157725084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
157825084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
157925084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
158080677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
158180677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
158280677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
158306656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
158406656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1585f4ddd8eeSStefano Zampini   }
158688ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
15874f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
1588d16cbb6bSStefano Zampini     IS        dummy;
1589d16cbb6bSStefano Zampini     Mat       B0_R;
1590d16cbb6bSStefano Zampini     PetscReal norm;
1591d16cbb6bSStefano Zampini 
15924f1b2e48SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
15934f1b2e48SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
1594d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
1595d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
1596d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
1597d16cbb6bSStefano Zampini     }
1598d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
1599d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1600d16cbb6bSStefano Zampini   }
1601d16cbb6bSStefano Zampini 
160288ebb749SStefano Zampini   if (n_vertices) {
160306656605SStefano Zampini     IS is_aux;
16043a50541eSStefano Zampini 
16056816873aSStefano Zampini     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
16066816873aSStefano Zampini       IS tis;
16076816873aSStefano Zampini 
16086816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
16096816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
16106816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
16116816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
16126816873aSStefano Zampini     } else {
16133a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
16146816873aSStefano Zampini     }
1615*a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
1616*a3df083aSStefano Zampini       ISLocalToGlobalMapping RtoN;
1617*a3df083aSStefano Zampini       Mat                    B,A_RVt;
1618*a3df083aSStefano Zampini       Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1619*a3df083aSStefano Zampini       PetscInt               *idxs_p0,n;
1620*a3df083aSStefano Zampini 
1621*a3df083aSStefano Zampini       ierr = MatGetSubMatrix(matis->A,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RVt);CHKERRQ(ierr);
1622*a3df083aSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_change,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1623*a3df083aSStefano Zampini       ierr = MatTranspose(B,MAT_REUSE_MATRIX,&B);CHKERRQ(ierr);
1624*a3df083aSStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
1625*a3df083aSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
1626*a3df083aSStefano Zampini       ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
1627*a3df083aSStefano Zampini       if (n != pcbddc->benign_n) {
1628*a3df083aSStefano Zampini         SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %d != %d\n",n,pcbddc->benign_n);
1629*a3df083aSStefano Zampini       }
1630*a3df083aSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
1631*a3df083aSStefano Zampini       ierr = MatZeroRows(B,pcbddc->benign_n,idxs_p0,0.,NULL,NULL);CHKERRQ(ierr);
1632*a3df083aSStefano Zampini       ierr = PetscFree(idxs_p0);CHKERRQ(ierr);
1633*a3df083aSStefano Zampini       ierr = MatMatMult(B,A_RVt,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&A_RV);CHKERRQ(ierr);
1634*a3df083aSStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
1635*a3df083aSStefano Zampini       ierr = MatDestroy(&A_RVt);CHKERRQ(ierr);
1636*a3df083aSStefano Zampini       ierr = MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1637*a3df083aSStefano Zampini       ierr = MatGetSubMatrix(matis->A,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
1638*a3df083aSStefano Zampini     } else {
16399577ea80SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
16409577ea80SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
164104708bb6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
1642*a3df083aSStefano Zampini     }
16434f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1644019a44ceSStefano Zampini       IS dummy;
1645019a44ceSStefano Zampini 
16464f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
16474f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1648019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1649019a44ceSStefano Zampini     }
165025084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
165188ebb749SStefano Zampini   }
165288ebb749SStefano Zampini 
165388ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1654f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
165506656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
165606656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
165706656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
165806656605SStefano Zampini     }
1659f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
166006656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
166106656605SStefano Zampini       PetscScalar *marray;
166206656605SStefano Zampini 
166306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
166406656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1665f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1666f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1667f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1668f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1669f4ddd8eeSStefano Zampini     }
1670f4ddd8eeSStefano Zampini   }
167106656605SStefano Zampini 
1672f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
167306656605SStefano Zampini     PetscScalar *marray;
167488ebb749SStefano Zampini 
167506656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
16768eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
167706656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
167888ebb749SStefano Zampini     }
16793301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
168006656605SStefano Zampini       n *= 2;
168188ebb749SStefano Zampini     }
168206656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
168306656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
168406656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
16858eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
168606656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
168706656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
168888ebb749SStefano Zampini     }
16893301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
169006656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
16918eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
169206656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
169306656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
169488ebb749SStefano Zampini       }
169588ebb749SStefano Zampini     } else {
1696c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1697c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
16981b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1699c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1700c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1701c0553b1fSStefano Zampini       }
170288ebb749SStefano Zampini     }
170306656605SStefano Zampini   }
1704019a44ceSStefano Zampini 
170506656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
17064f1b2e48SStefano Zampini   p0_lidx_I = NULL;
17074f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1708d12edf2fSStefano Zampini     const PetscInt *idxs;
1709d12edf2fSStefano Zampini 
1710d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
17114f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
17124f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
17134f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
17144f1b2e48SStefano Zampini     }
1715d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1716d12edf2fSStefano Zampini   }
1717d16cbb6bSStefano Zampini 
171806656605SStefano Zampini   /* vertices */
171906656605SStefano Zampini   if (n_vertices) {
172016f15bc4SStefano Zampini 
1721ffd830a3SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
172204708bb6SStefano Zampini 
172316f15bc4SStefano Zampini     if (n_R) {
172406656605SStefano Zampini       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
172506656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
172616f15bc4SStefano Zampini       PetscScalar  *x,*y;
172704708bb6SStefano Zampini       PetscBool    isseqaij;
172806656605SStefano Zampini 
172921eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
1730ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
1731ffd830a3SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
1732ffd830a3SStefano Zampini       } else {
1733ca92afb2SStefano Zampini         PetscScalar    *av,*array;
1734ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
1735ca92afb2SStefano Zampini         PetscInt       n;
1736ca92afb2SStefano Zampini         PetscBool      flg_row;
1737ffd830a3SStefano Zampini 
1738ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
1739ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
1740ca92afb2SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
1741ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1742ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
1743ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
1744ca92afb2SStefano Zampini           PetscInt j;
1745ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
1746ffd830a3SStefano Zampini         }
1747ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1748ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1749ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
1750ffd830a3SStefano Zampini       }
1751ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
17526816873aSStefano Zampini       if (F) { /* TODO could be optimized for symmetric problems */
1753*a3df083aSStefano Zampini         if (need_benign_correction) {
1754*a3df083aSStefano Zampini           PetscScalar      *marr;
1755*a3df083aSStefano Zampini           PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1756*a3df083aSStefano Zampini 
1757*a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
1758*a3df083aSStefano Zampini           for (i=0;i<n_vertices;i++) {
1759*a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1760*a3df083aSStefano Zampini             ierr = PCBDDCReuseSolversChangeInterior(reuse_mumps,pcbddc->vec1_R,NULL,PETSC_FALSE);CHKERRQ(ierr);
1761*a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1762*a3df083aSStefano Zampini           }
1763*a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
1764*a3df083aSStefano Zampini         }
176506656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
1766*a3df083aSStefano Zampini         if (need_benign_correction) {
1767*a3df083aSStefano Zampini           PetscScalar      *marr;
1768*a3df083aSStefano Zampini           PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1769*a3df083aSStefano Zampini 
1770*a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
1771*a3df083aSStefano Zampini           for (i=0;i<n_vertices;i++) {
1772*a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1773*a3df083aSStefano Zampini             ierr = PCBDDCReuseSolversChangeInterior(reuse_mumps,pcbddc->vec1_R,NULL,PETSC_TRUE);CHKERRQ(ierr);
1774*a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1775*a3df083aSStefano Zampini           }
1776*a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
1777*a3df083aSStefano Zampini         }
177806656605SStefano Zampini       } else {
177906656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
178006656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
1781ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
1782ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
178306656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
178406656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
178506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
178606656605SStefano Zampini         }
178706656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
178806656605SStefano Zampini       }
178980677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1790ffd830a3SStefano Zampini       /* S_VV and S_CV */
179106656605SStefano Zampini       if (n_constraints) {
179206656605SStefano Zampini         Mat B;
179380677318SStefano Zampini 
1794ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
179580677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
1796ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1797ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
179880677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
179980677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
180080677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
180180677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
180280677318SStefano Zampini         }
1803ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
180480677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
180580677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
1806ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
180780677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
180806656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
1809ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
1810ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
181106656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
181206656605SStefano Zampini       }
181304708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
181404708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
181504708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
181604708bb6SStefano Zampini       }
1817ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1818ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
1819ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
1820ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
1821ffd830a3SStefano Zampini       }
182206656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
182380677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
182406656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
182506656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
182606656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
182706656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
182806656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
182906656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
183006656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1831d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1832019a44ceSStefano Zampini     } else {
1833d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1834d16cbb6bSStefano Zampini     }
18354f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1836019a44ceSStefano Zampini       const PetscScalar *vals;
1837019a44ceSStefano Zampini       const PetscInt    *idxs;
18384f1b2e48SStefano Zampini       PetscInt          n,j,primal_idx;
1839019a44ceSStefano Zampini 
18404f1b2e48SStefano Zampini       ierr = MatGetRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
18414f1b2e48SStefano Zampini       primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + i;
1842d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
18434f1b2e48SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+idxs[j]] = vals[j];
18444f1b2e48SStefano Zampini         coarse_submat_vals[idxs[j]*pcbddc->local_primal_size+primal_idx] = vals[j];
1845019a44ceSStefano Zampini       }
18464f1b2e48SStefano Zampini       ierr = MatRestoreRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
184716f15bc4SStefano Zampini     }
184821eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1849d16cbb6bSStefano Zampini 
185006656605SStefano Zampini     /* coarse basis functions */
185106656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
185216f15bc4SStefano Zampini       PetscScalar *y;
185316f15bc4SStefano Zampini 
1854ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
185506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
185606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
185706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185906656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
186006656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
186106656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
186206656605SStefano Zampini 
186306656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
18644f1b2e48SStefano Zampini         PetscInt j;
18654f1b2e48SStefano Zampini 
186606656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
186706656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
186806656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
186906656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187006656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
18714f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
187206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
187306656605SStefano Zampini       }
187406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
187506656605SStefano Zampini     }
187604708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
187704708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
187806656605SStefano Zampini   }
187906656605SStefano Zampini 
188006656605SStefano Zampini   if (n_constraints) {
188106656605SStefano Zampini     Mat B;
188206656605SStefano Zampini 
1883ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
188406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
188580677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
188606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
188706656605SStefano Zampini     if (n_vertices) {
188880677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
188980677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
189080677318SStefano Zampini       } else {
189180677318SStefano Zampini         Mat S_VCt;
189280677318SStefano Zampini 
1893ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
1894ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
1895ffd830a3SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B);CHKERRQ(ierr);
1896ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
1897ffd830a3SStefano Zampini         }
189880677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
189980677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
190080677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
190180677318SStefano Zampini       }
190206656605SStefano Zampini     }
190306656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
190406656605SStefano Zampini     /* coarse basis functions */
190506656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
190606656605SStefano Zampini       PetscScalar *y;
190706656605SStefano Zampini 
1908ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
190906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
191006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
191106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
191206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
191306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
191406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
191506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
19164f1b2e48SStefano Zampini         PetscInt j;
19174f1b2e48SStefano Zampini 
191806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
191906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
192006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
192106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
192206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
19234f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
192406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
192506656605SStefano Zampini       }
192606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
192706656605SStefano Zampini     }
192806656605SStefano Zampini   }
192980677318SStefano Zampini   if (n_constraints) {
193080677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
193180677318SStefano Zampini   }
19324f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
1933019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1934019a44ceSStefano Zampini 
193506656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
19363301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
1937ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
1938ffd830a3SStefano Zampini     PetscScalar *marray;
193906656605SStefano Zampini 
194006656605SStefano Zampini     if (n_constraints) {
1941ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
194206656605SStefano Zampini 
1943ffd830a3SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
194406656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
1945ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
194616f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
194706656605SStefano Zampini       if (n_vertices) {
1948ffd830a3SStefano Zampini         Mat S_VCT;
194906656605SStefano Zampini 
195006656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
1951ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
195216f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
195306656605SStefano Zampini       }
1954ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
195506656605SStefano Zampini     }
195616f15bc4SStefano Zampini     if (n_vertices && n_R) {
1957ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
1958ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
1959ffd830a3SStefano Zampini       PetscInt       n;
1960ffd830a3SStefano Zampini       PetscBool      flg_row;
196106656605SStefano Zampini 
1962ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
1963ffd830a3SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
1964ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1965ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
1966ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
1967ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
1968ffd830a3SStefano Zampini         PetscInt j;
1969ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
1970ffd830a3SStefano Zampini       }
1971ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
1972ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1973ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
197406656605SStefano Zampini     }
197506656605SStefano Zampini 
1976ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
1977ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
1978ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
1979ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
1980ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
198106656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
198206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
198306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
198406656605SStefano Zampini     }
1985ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
1986ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
1987ffd830a3SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
1988ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
1989ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
1990ffd830a3SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1991ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1992ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
199306656605SStefano Zampini     }
1994ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
199506656605SStefano Zampini     /* coarse basis functions */
199606656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
199706656605SStefano Zampini       PetscScalar *y;
199806656605SStefano Zampini 
1999ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
200006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
200106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
200206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
200306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
200406656605SStefano Zampini       if (i<n_vertices) {
200506656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
200606656605SStefano Zampini       }
200706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
200806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
200906656605SStefano Zampini 
201006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
201106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
201206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
201306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
201606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
201706656605SStefano Zampini       }
201806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
201906656605SStefano Zampini     }
2020ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2021ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
202206656605SStefano Zampini   }
2023d62866d3SStefano Zampini   /* free memory */
202488ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
202506656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
202606656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
202706656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
202806656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2029d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2030d62866d3SStefano Zampini   if (n_vertices) {
2031d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2032d62866d3SStefano Zampini   }
2033d62866d3SStefano Zampini   if (n_constraints) {
2034d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2035d62866d3SStefano Zampini   }
203688ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
203788ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
203888ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2039d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
204088ebb749SStefano Zampini     Mat         coarse_sub_mat;
204125084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
204288ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
204388ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
204488ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
20458bec7fa6SStefano Zampini     Mat         C_B,CPHI;
20468bec7fa6SStefano Zampini     IS          is_dummy;
20478bec7fa6SStefano Zampini     Vec         mones;
204888ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
204988ebb749SStefano Zampini     PetscReal   real_value;
205088ebb749SStefano Zampini 
2051*a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2052*a3df083aSStefano Zampini       Mat A;
2053*a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2054*a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2055*a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2056*a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2057*a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2058*a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2059*a3df083aSStefano Zampini     } else {
206088ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
206188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
206288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
206388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2064*a3df083aSStefano Zampini     }
206588ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
206688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2067ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
206888ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
206988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
207088ebb749SStefano Zampini     }
207188ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
207288ebb749SStefano Zampini 
207325084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
20743301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
207525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2076ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
207788ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
207888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
207988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
208088ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
208188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
208288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
208388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
208488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
208588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
208688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
208788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
208888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
208988ebb749SStefano Zampini     } else {
209088ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
209188ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
209288ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
209388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
209488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
209588ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
209688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
209788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
209888ebb749SStefano Zampini     }
209988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
210088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
210188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
210288ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
21034f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2104d12edf2fSStefano Zampini       Mat         B0_I,B0_B,B0_BPHI,B0_IPHI;
2105d12edf2fSStefano Zampini       PetscScalar *data,*data2;
21064f1b2e48SStefano Zampini       PetscInt    j;
2107d12edf2fSStefano Zampini 
21084f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
21094f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
21104f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
2111d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
2112d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2113d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2114d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
21154f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
21164f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2117d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
21184f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
21194f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
21204f1b2e48SStefano Zampini         }
2121d12edf2fSStefano Zampini       }
2122d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2123d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2124d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2125d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2126d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2127d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
2128d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
2129d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2130d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
2131d12edf2fSStefano Zampini     }
2132d12edf2fSStefano Zampini #if 0
2133d12edf2fSStefano Zampini   {
2134d12edf2fSStefano Zampini     PetscViewer viewer;
2135d12edf2fSStefano Zampini     char filename[256];
2136ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2137d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2138d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2139ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2140ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2141ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2142d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
2143ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2144ffd830a3SStefano Zampini     ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
2145ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2146ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2147ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2148ffd830a3SStefano Zampini     }
2149ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2150ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2151ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2152ffd830a3SStefano Zampini     }
2153ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_B) {
2154ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2155ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2156ffd830a3SStefano Zampini     }
2157d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2158d12edf2fSStefano Zampini   }
2159d12edf2fSStefano Zampini #endif
216081d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
21618bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
21621575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
216306656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
21648bec7fa6SStefano Zampini 
21658bec7fa6SStefano Zampini     /* check constraints */
21664f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
21678bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
21688bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
21698bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
21708bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
21718bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
21728bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
21738bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2174bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2175ffd830a3SStefano Zampini       if (!pcbddc->symmetric_primal) {
2176bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2177bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2178bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2179bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2180bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
218188ebb749SStefano Zampini       }
21828bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
21838bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
21848bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
21858bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
2186d12edf2fSStefano Zampini     }
218725084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
218888ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
218988ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
219088ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
219188ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
219288ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
219388ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
219488ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
219588ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
219688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
219788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2198ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
219988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
220088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
220188ebb749SStefano Zampini     }
220288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
220388ebb749SStefano Zampini   }
22048629588bSStefano Zampini   /* get back data */
22058629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
220688ebb749SStefano Zampini   PetscFunctionReturn(0);
220788ebb749SStefano Zampini }
220888ebb749SStefano Zampini 
220988ebb749SStefano Zampini #undef __FUNCT__
2210d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2211d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2212aa0d41d4SStefano Zampini {
2213d65f70fdSStefano Zampini   Mat            *work_mat;
2214d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2215d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2216d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
2217aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2218aa0d41d4SStefano Zampini 
2219aa0d41d4SStefano Zampini   PetscFunctionBegin;
2220d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2221d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2222d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2223d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2224aa0d41d4SStefano Zampini 
2225d65f70fdSStefano Zampini   if (!rsorted) {
2226906d46d4SStefano Zampini     const PetscInt *idxs;
2227906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2228aa0d41d4SStefano Zampini 
2229d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2230d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2231d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2232d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2233aa0d41d4SStefano Zampini     }
2234d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2235d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2236d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2237d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2238aa0d41d4SStefano Zampini     }
2239d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2240d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2241d65f70fdSStefano Zampini   } else {
2242d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2243d65f70fdSStefano Zampini     isrow_s = isrow;
2244aa0d41d4SStefano Zampini   }
2245906d46d4SStefano Zampini 
2246d65f70fdSStefano Zampini   if (!csorted) {
2247d65f70fdSStefano Zampini     if (isrow == iscol) {
2248d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2249d65f70fdSStefano Zampini       iscol_s = isrow_s;
2250d65f70fdSStefano Zampini     } else {
2251d65f70fdSStefano Zampini       const PetscInt *idxs;
2252d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
2253906d46d4SStefano Zampini 
2254d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2255d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2256d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2257d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2258d65f70fdSStefano Zampini       }
2259d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2260d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2261d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2262d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2263d65f70fdSStefano Zampini       }
2264d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2265d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2266d65f70fdSStefano Zampini     }
2267d65f70fdSStefano Zampini   } else {
2268d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2269d65f70fdSStefano Zampini     iscol_s = iscol;
2270d65f70fdSStefano Zampini   }
2271d65f70fdSStefano Zampini 
2272d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2273d65f70fdSStefano Zampini 
2274d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2275906d46d4SStefano Zampini     Mat      new_mat;
2276d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2277906d46d4SStefano Zampini 
2278d65f70fdSStefano Zampini     if (!rsorted) {
2279d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2280d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2281d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2282d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2283906d46d4SStefano Zampini       }
2284d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2285d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2286d65f70fdSStefano Zampini     } else {
2287d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2288906d46d4SStefano Zampini     }
2289d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2290d65f70fdSStefano Zampini 
2291d65f70fdSStefano Zampini     if (!csorted) {
2292d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2293d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2294d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2295d65f70fdSStefano Zampini       } else {
2296d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2297d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2298d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2299d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2300d65f70fdSStefano Zampini         }
2301d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2302d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2303d65f70fdSStefano Zampini       }
2304d65f70fdSStefano Zampini     } else {
2305d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2306d65f70fdSStefano Zampini     }
2307d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2308d65f70fdSStefano Zampini 
2309d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2310d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2311d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2312d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2313d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2314d65f70fdSStefano Zampini   }
2315d65f70fdSStefano Zampini 
2316d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2317d65f70fdSStefano Zampini   *B = work_mat[0];
2318d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2319d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2320d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2321d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2322d65f70fdSStefano Zampini }
2323d65f70fdSStefano Zampini 
2324d65f70fdSStefano Zampini #undef __FUNCT__
23255e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
23265e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2327aa0d41d4SStefano Zampini {
2328aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
23295e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2330d65f70fdSStefano Zampini   Mat            new_mat;
23315e8657edSStefano Zampini   IS             is_local,is_global;
2332d65f70fdSStefano Zampini   PetscInt       local_size;
2333d65f70fdSStefano Zampini   PetscBool      isseqaij;
2334aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2335aa0d41d4SStefano Zampini 
2336aa0d41d4SStefano Zampini   PetscFunctionBegin;
2337aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
23385e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
23395e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2340b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2341aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2342d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2343aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2344906d46d4SStefano Zampini 
2345906d46d4SStefano Zampini   /* check */
2346906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2347906d46d4SStefano Zampini     Vec       x,x_change;
2348906d46d4SStefano Zampini     PetscReal error;
2349906d46d4SStefano Zampini 
23505e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2351906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
23525e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2353e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2354e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2355d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2356e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2357e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2358906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2359906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2360906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2361906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2362906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2363906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2364906d46d4SStefano Zampini   }
2365906d46d4SStefano Zampini 
236622d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
23679b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
236822d5777bSStefano Zampini   if (isseqaij) {
23691cf9b237SStefano Zampini     Mat M;
23701cf9b237SStefano Zampini 
23711cf9b237SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
23721cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
23731cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2374aa0d41d4SStefano Zampini   } else {
23751cf9b237SStefano Zampini     Mat work_mat,M;
23761cf9b237SStefano Zampini 
2377aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
23781cf9b237SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
23791cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
23801cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2381aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2382aa0d41d4SStefano Zampini   }
23833301b35fSStefano Zampini   if (matis->A->symmetric_set) {
23843301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2385e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
23863301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2387e496cd5dSStefano Zampini #endif
23883301b35fSStefano Zampini   }
238945a1bb75SStefano Zampini   /*
239045a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2391d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
239245a1bb75SStefano Zampini   */
2393d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2394aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2395aa0d41d4SStefano Zampini }
2396aa0d41d4SStefano Zampini 
2397aa0d41d4SStefano Zampini #undef __FUNCT__
2398a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
23998ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2400a64d13efSStefano Zampini {
2401a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2402a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2403d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
240453892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
24053a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
24063a50541eSStefano Zampini   PetscInt        vbs,bs;
24076816873aSStefano Zampini   PetscBT         bitmask=NULL;
2408a64d13efSStefano Zampini   PetscErrorCode  ierr;
2409a64d13efSStefano Zampini 
2410a64d13efSStefano Zampini   PetscFunctionBegin;
2411b23d619eSStefano Zampini   /*
2412b23d619eSStefano Zampini     No need to setup local scatters if
2413b23d619eSStefano Zampini       - primal space is unchanged
2414b23d619eSStefano Zampini         AND
2415b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2416b23d619eSStefano Zampini         AND
2417b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2418b23d619eSStefano Zampini   */
2419b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2420f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2421f4ddd8eeSStefano Zampini   }
2422f4ddd8eeSStefano Zampini   /* destroy old objects */
2423f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2424f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2425f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2426a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2427b371cd4fSStefano Zampini   n_B = pcis->n_B;
2428b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2429b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
24303a50541eSStefano Zampini 
2431a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
24326816873aSStefano Zampini 
243353892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
24346816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
2435854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2436a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2437a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
24380e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2439a64d13efSStefano Zampini     }
2440a64d13efSStefano Zampini 
2441a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
24424641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
24436816873aSStefano Zampini         idx_R_local[n_R++] = i;
2444a64d13efSStefano Zampini       }
2445a64d13efSStefano Zampini     }
244653892102SStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
24476816873aSStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
24486816873aSStefano Zampini 
244953892102SStefano Zampini     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
245053892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
24516816873aSStefano Zampini   }
24523a50541eSStefano Zampini 
24533a50541eSStefano Zampini   /* Block code */
24543a50541eSStefano Zampini   vbs = 1;
24553a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
24563a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
24573a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
24583a50541eSStefano Zampini     PetscInt  *vary;
2459d3df7717SStefano Zampini     if (!sub_schurs->reuse_mumps) {
2460785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
24613a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2462d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2463d3df7717SStefano Zampini       /* it is ok to check this way since local_primal_ref_node are always sorted by local numbering and idx_R_local is obtained as a complement */
24640e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2465d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
24663a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
24673a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
24683a50541eSStefano Zampini           break;
24693a50541eSStefano Zampini         }
24703a50541eSStefano Zampini       }
2471d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2472d3df7717SStefano Zampini     } else {
2473d3df7717SStefano Zampini       /* Verify directly the R set */
2474d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2475d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2476d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2477d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2478d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2479d3df7717SStefano Zampini             break;
2480d3df7717SStefano Zampini           }
2481d3df7717SStefano Zampini         }
2482d3df7717SStefano Zampini       }
2483d3df7717SStefano Zampini     }
24843a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
24853a50541eSStefano Zampini       vbs = bs;
24863a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
24873a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
24883a50541eSStefano Zampini       }
24893a50541eSStefano Zampini     }
24903a50541eSStefano Zampini   }
24913a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
249253892102SStefano Zampini   if (sub_schurs->reuse_mumps) {
249353892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
249453892102SStefano Zampini 
249553892102SStefano Zampini     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
249653892102SStefano Zampini     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
249753892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
249853892102SStefano Zampini     reuse_mumps->is_R = pcbddc->is_R_local;
249953892102SStefano Zampini   } else {
25003a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
250153892102SStefano Zampini   }
2502a64d13efSStefano Zampini 
2503a64d13efSStefano Zampini   /* print some info if requested */
2504a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2505a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2506a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
25071575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2508a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2509a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
25104f1b2e48SStefano 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->benign_n,pcbddc->local_primal_size);CHKERRQ(ierr);
2511a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2512a64d13efSStefano Zampini   }
2513a64d13efSStefano Zampini 
2514a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
25156816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
25166816873aSStefano Zampini     IS       is_aux1,is_aux2;
25176816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
25186816873aSStefano Zampini 
25193a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2520854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2521854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2522a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
25234641a718SStefano Zampini     for (i=0; i<n_D; i++) {
25244641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
25254641a718SStefano Zampini     }
2526a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2527a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
25284641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
25294641a718SStefano Zampini         aux_array1[j++] = i;
2530a64d13efSStefano Zampini       }
2531a64d13efSStefano Zampini     }
2532a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2533a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2534a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
25354641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
25364641a718SStefano Zampini         aux_array2[j++] = i;
2537a64d13efSStefano Zampini       }
2538a64d13efSStefano Zampini     }
2539a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2540a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2541a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2542a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2543a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2544a64d13efSStefano Zampini 
25458eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2546785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2547a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
25484641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
25494641a718SStefano Zampini           aux_array1[j++] = i;
2550a64d13efSStefano Zampini         }
2551a64d13efSStefano Zampini       }
2552a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2553a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2554a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2555a64d13efSStefano Zampini     }
25564641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
25573a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2558d62866d3SStefano Zampini   } else {
255953892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
25606816873aSStefano Zampini     IS               tis;
25616816873aSStefano Zampini     PetscInt         schur_size;
25626816873aSStefano Zampini 
256353892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
25646816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
256553892102SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
25666816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
25676816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
25686816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
25696816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
25706816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2571d62866d3SStefano Zampini     }
2572d62866d3SStefano Zampini   }
2573a64d13efSStefano Zampini   PetscFunctionReturn(0);
2574a64d13efSStefano Zampini }
2575a64d13efSStefano Zampini 
2576304d26faSStefano Zampini 
2577304d26faSStefano Zampini #undef __FUNCT__
2578304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2579684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2580304d26faSStefano Zampini {
2581304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2582304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2583304d26faSStefano Zampini   PC             pc_temp;
2584304d26faSStefano Zampini   Mat            A_RR;
2585f4ddd8eeSStefano Zampini   MatReuse       reuse;
2586304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2587304d26faSStefano Zampini   PetscReal      value;
258804708bb6SStefano Zampini   PetscInt       n_D,n_R;
25899577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
2590304d26faSStefano Zampini   PetscErrorCode ierr;
2591e604994aSStefano Zampini   /* prefixes stuff */
2592312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2593e604994aSStefano Zampini   size_t         len;
2594304d26faSStefano Zampini 
2595304d26faSStefano Zampini   PetscFunctionBegin;
2596304d26faSStefano Zampini 
2597e604994aSStefano Zampini   /* compute prefixes */
2598e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2599e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2600e604994aSStefano Zampini   if (!pcbddc->current_level) {
2601e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2602e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2603e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2604e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2605e604994aSStefano Zampini   } else {
2606e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2607312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2608e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2609e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2610312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2611312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
261234d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
261334d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2614e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2615e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2616e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
2617e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
2618e604994aSStefano Zampini   }
2619e604994aSStefano Zampini 
2620304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
2621684f6988SStefano Zampini   if (dirichlet) {
2622d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2623*a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit && pcbddc->dbg_flag) {
2624*a3df083aSStefano Zampini       Mat    A_IIn;
2625*a3df083aSStefano Zampini 
2626*a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
2627*a3df083aSStefano Zampini       ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
2628*a3df083aSStefano Zampini       pcis->A_II = A_IIn;
2629*a3df083aSStefano Zampini     }
26303301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
26313301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2632964fefecSStefano Zampini     }
2633ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
2634964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
2635304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
2636304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
2637304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
2638304d26faSStefano Zampini       /* default */
2639304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
2640e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
26419577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2642304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
26439577ea80SStefano Zampini       if (issbaij) {
26449577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
26459577ea80SStefano Zampini       } else {
2646304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
26479577ea80SStefano Zampini       }
2648304d26faSStefano Zampini       /* Allow user's customization */
2649304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
2650304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2651304d26faSStefano Zampini     }
2652d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
2653d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2654d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2655d62866d3SStefano Zampini 
2656d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
2657d5574798SStefano Zampini     }
2658304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2659304d26faSStefano Zampini     if (!n_D) {
2660304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
2661304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2662304d26faSStefano Zampini     }
2663304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
2664304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
2665304d26faSStefano Zampini     /* set ksp_D into pcis data */
2666304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
2667304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
2668304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
2669684f6988SStefano Zampini   }
2670304d26faSStefano Zampini 
2671304d26faSStefano Zampini   /* NEUMANN PROBLEM */
2672684f6988SStefano Zampini   A_RR = 0;
2673684f6988SStefano Zampini   if (neumann) {
2674d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
267504708bb6SStefano Zampini     PetscInt        ibs,mbs;
267604708bb6SStefano Zampini     PetscBool       issbaij;
267704708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
2678f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
26798ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
2680f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
2681f4ddd8eeSStefano Zampini       PetscInt nn_R;
268281d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
2683f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2684f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
2685f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
2686f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
2687f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2688f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2689f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
2690727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
2691f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2692f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
2693f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
2694f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
2695f4ddd8eeSStefano Zampini         }
2696f4ddd8eeSStefano Zampini       }
2697f4ddd8eeSStefano Zampini       /* last check */
2698d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
2699f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2700f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2701f4ddd8eeSStefano Zampini       }
2702f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
2703f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
2704f4ddd8eeSStefano Zampini     }
2705f4ddd8eeSStefano Zampini     /* extract A_RR */
2706af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
2707af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
270804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
270904708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
271004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
271104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
271204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2713af732b37SStefano Zampini       } else {
271404708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
27156816873aSStefano Zampini       }
271604708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
271704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
271804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
271904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
272004708bb6SStefano Zampini       } else {
272104708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
272204708bb6SStefano Zampini       }
272304708bb6SStefano Zampini     }
2724f4ddd8eeSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
27253301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
27263301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
27276816873aSStefano Zampini     }
2728*a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit && pcbddc->dbg_flag) {
2729*a3df083aSStefano Zampini       Mat A_RRn;
2730*a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RRn);CHKERRQ(ierr);
2731*a3df083aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2732*a3df083aSStefano Zampini       A_RR = A_RRn;
2733*a3df083aSStefano Zampini     }
2734f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
2735304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
2736304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
2737304d26faSStefano Zampini       /* default */
2738304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
2739e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
2740304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
27419577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
27429577ea80SStefano Zampini       if (issbaij) {
27439577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
27449577ea80SStefano Zampini       } else {
2745304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
27469577ea80SStefano Zampini       }
2747304d26faSStefano Zampini       /* Allow user's customization */
2748304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
2749304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2750304d26faSStefano Zampini     }
2751304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2752304d26faSStefano Zampini     if (!n_R) {
2753304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2754304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2755304d26faSStefano Zampini     }
2756d62866d3SStefano Zampini     /* Reuse MUMPS solver if it is present */
2757d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2758d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2759d62866d3SStefano Zampini 
2760d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
2761d62866d3SStefano Zampini     }
2762ffd830a3SStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2763304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
2764304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2765684f6988SStefano Zampini   }
27666816873aSStefano Zampini   /* free Neumann problem's matrix */
27676816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2768304d26faSStefano Zampini 
2769304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
27700fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2771684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
2772684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
27731575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2774684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2775684f6988SStefano Zampini     }
2776684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
27770fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
27780fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
27790fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
27800fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
27810fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2782304d26faSStefano Zampini       /* need to be adapted? */
2783b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2784b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2785b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2786304d26faSStefano Zampini       /* print info */
2787304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2788e604994aSStefano 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);
2789304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2790304d26faSStefano Zampini       }
2791b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2792298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2793304d26faSStefano Zampini       }
2794684f6988SStefano Zampini     }
2795684f6988SStefano Zampini     if (neumann) { /* Neumann */
27966816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
27970fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
27980fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
27990fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
28000fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
28010fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2802304d26faSStefano Zampini       /* need to be adapted? */
2803b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2804b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2805304d26faSStefano Zampini       /* print info */
2806304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2807e604994aSStefano 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);
2808304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2809304d26faSStefano Zampini       }
2810b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2811298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2812304d26faSStefano Zampini       }
28130fccc4e9SStefano Zampini     }
2814684f6988SStefano Zampini   }
2815304d26faSStefano Zampini   PetscFunctionReturn(0);
2816304d26faSStefano Zampini }
2817304d26faSStefano Zampini 
2818304d26faSStefano Zampini #undef __FUNCT__
2819ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
282080677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2821674ae819SStefano Zampini {
2822674ae819SStefano Zampini   PetscErrorCode  ierr;
2823674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2824be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2825674ae819SStefano Zampini 
2826674ae819SStefano Zampini   PetscFunctionBegin;
2827be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
282880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
282920c7b377SStefano Zampini   }
283080677318SStefano Zampini   if (!pcbddc->switch_static) {
283180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
283280677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
283380677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
283420c7b377SStefano Zampini     }
2835be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
283680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
283780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
283820c7b377SStefano Zampini     } else {
2839be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2840be83ff47SStefano Zampini 
284153892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
284253892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
284320c7b377SStefano Zampini     }
2844be83ff47SStefano Zampini   } else {
284580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
284680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
284780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
284880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
284980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
285080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
285180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
285280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
285380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2854674ae819SStefano Zampini     }
2855674ae819SStefano Zampini   }
2856be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
285780677318SStefano Zampini     if (applytranspose) {
285880677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
285980677318SStefano Zampini     } else {
286080677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
286180677318SStefano Zampini     }
2862be83ff47SStefano Zampini   } else {
2863be83ff47SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2864be83ff47SStefano Zampini 
2865be83ff47SStefano Zampini     if (applytranspose) {
28665a05ddb0SStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2867be83ff47SStefano Zampini     } else {
28685a05ddb0SStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2869be83ff47SStefano Zampini     }
2870be83ff47SStefano Zampini   }
287180677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
287280677318SStefano Zampini   if (!pcbddc->switch_static) {
2873be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
287480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
287580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2876be83ff47SStefano Zampini     } else {
2877be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2878be83ff47SStefano Zampini 
287953892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
288053892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2881be83ff47SStefano Zampini     }
288280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
288380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
288480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
288580677318SStefano Zampini     }
288680677318SStefano Zampini   } else {
288780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
288880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
288980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
289080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
289180677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
289280677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
289380677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
289480677318SStefano Zampini     }
289580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
289680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
289780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
289880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2899674ae819SStefano Zampini   }
2900674ae819SStefano Zampini   PetscFunctionReturn(0);
2901674ae819SStefano Zampini }
2902674ae819SStefano Zampini 
2903dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2904674ae819SStefano Zampini #undef __FUNCT__
2905674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2906dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2907674ae819SStefano Zampini {
2908674ae819SStefano Zampini   PetscErrorCode ierr;
2909674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2910674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2911674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2912674ae819SStefano Zampini 
2913674ae819SStefano Zampini   PetscFunctionBegin;
2914dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2915dc359a40SStefano Zampini   if (applytranspose) {
2916674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
29178eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2918dc359a40SStefano Zampini   } else {
2919674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2920674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
292115aaf578SStefano Zampini   }
2922efc2fbd9SStefano Zampini 
2923efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
29244f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2925efc2fbd9SStefano Zampini     PetscScalar *array;
29264f1b2e48SStefano Zampini     PetscInt    j;
2927efc2fbd9SStefano Zampini 
2928efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
29294f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
2930efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2931efc2fbd9SStefano Zampini   }
2932efc2fbd9SStefano Zampini 
293312edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
293412edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
293512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
293612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
293712edc857SStefano Zampini 
29389f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
293912edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
294012edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
294151694757SStefano Zampini     Mat coarse_mat;
2942964fefecSStefano Zampini     Vec rhs,sol;
294351694757SStefano Zampini     MatNullSpace nullsp;
2944964fefecSStefano Zampini 
2945964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2946964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
294751694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
294851694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
294951694757SStefano Zampini     if (nullsp) {
295051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
295151694757SStefano Zampini     }
295212edc857SStefano Zampini     if (applytranspose) {
2953964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
295412edc857SStefano Zampini     } else {
2955964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
295612edc857SStefano Zampini     }
295751694757SStefano Zampini     if (nullsp) {
295851694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
295951694757SStefano Zampini     }
296012edc857SStefano Zampini   }
2961674ae819SStefano Zampini 
2962674ae819SStefano Zampini   /* Local solution on R nodes */
296380677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
296480677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
29659f00e9b4SStefano Zampini   }
2966674ae819SStefano Zampini 
29679f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
29689f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
296912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2970674ae819SStefano Zampini 
2971674ae819SStefano Zampini   /* Sum contributions from two levels */
2972dc359a40SStefano Zampini   if (applytranspose) {
2973dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2974dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2975dc359a40SStefano Zampini   } else {
2976674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
29778eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2978dc359a40SStefano Zampini   }
2979efc2fbd9SStefano Zampini   /* store p0 */
29804f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2981efc2fbd9SStefano Zampini     PetscScalar *array;
29824f1b2e48SStefano Zampini     PetscInt    j;
2983efc2fbd9SStefano Zampini 
2984efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
29854f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
2986efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2987efc2fbd9SStefano Zampini   }
2988674ae819SStefano Zampini   PetscFunctionReturn(0);
2989674ae819SStefano Zampini }
2990674ae819SStefano Zampini 
2991674ae819SStefano Zampini #undef __FUNCT__
2992674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
299312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2994674ae819SStefano Zampini {
2995674ae819SStefano Zampini   PetscErrorCode ierr;
2996674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
299758da7f69SStefano Zampini   PetscScalar    *array;
299812edc857SStefano Zampini   Vec            from,to;
2999674ae819SStefano Zampini 
3000674ae819SStefano Zampini   PetscFunctionBegin;
300112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
300212edc857SStefano Zampini     from = pcbddc->coarse_vec;
300312edc857SStefano Zampini     to = pcbddc->vec1_P;
300412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
300512edc857SStefano Zampini       Vec tvec;
300658da7f69SStefano Zampini 
300758da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
300858da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
300912edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
301058da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
301158da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
301258da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
301312edc857SStefano Zampini     }
301412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
301512edc857SStefano Zampini     from = pcbddc->vec1_P;
301612edc857SStefano Zampini     to = pcbddc->coarse_vec;
301712edc857SStefano Zampini   }
301812edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3019674ae819SStefano Zampini   PetscFunctionReturn(0);
3020674ae819SStefano Zampini }
3021674ae819SStefano Zampini 
3022674ae819SStefano Zampini #undef __FUNCT__
3023674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
302412edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3025674ae819SStefano Zampini {
3026674ae819SStefano Zampini   PetscErrorCode ierr;
3027674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
302858da7f69SStefano Zampini   PetscScalar    *array;
302912edc857SStefano Zampini   Vec            from,to;
3030674ae819SStefano Zampini 
3031674ae819SStefano Zampini   PetscFunctionBegin;
303212edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
303312edc857SStefano Zampini     from = pcbddc->coarse_vec;
303412edc857SStefano Zampini     to = pcbddc->vec1_P;
303512edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
303612edc857SStefano Zampini     from = pcbddc->vec1_P;
303712edc857SStefano Zampini     to = pcbddc->coarse_vec;
303812edc857SStefano Zampini   }
303912edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
304012edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
304112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
304212edc857SStefano Zampini       Vec tvec;
304358da7f69SStefano Zampini 
304412edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
304558da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
304658da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
304758da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
304858da7f69SStefano Zampini     }
304958da7f69SStefano Zampini   } else {
305058da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
305158da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
305212edc857SStefano Zampini     }
305312edc857SStefano Zampini   }
3054674ae819SStefano Zampini   PetscFunctionReturn(0);
3055674ae819SStefano Zampini }
3056674ae819SStefano Zampini 
3057984c4197SStefano Zampini /* uncomment for testing purposes */
3058984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3059674ae819SStefano Zampini #undef __FUNCT__
3060674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3061674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3062674ae819SStefano Zampini {
3063674ae819SStefano Zampini   PetscErrorCode    ierr;
3064674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3065674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3066674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3067984c4197SStefano Zampini   /* one and zero */
3068984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3069984c4197SStefano Zampini   /* space to store constraints and their local indices */
30709162d606SStefano Zampini   PetscScalar       *constraints_data;
30719162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
30729162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
30739162d606SStefano Zampini   PetscInt          *constraints_n;
3074984c4197SStefano Zampini   /* iterators */
3075b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3076984c4197SStefano Zampini   /* BLAS integers */
3077e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3078e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3079c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3080727cdba6SStefano Zampini   /* reuse */
30810e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
30820e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3083984c4197SStefano Zampini   /* change of basis */
3084b3d85658SStefano Zampini   PetscBool         qr_needed;
30859162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3086984c4197SStefano Zampini   /* auxiliary stuff */
308764efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
30888a0068c3SStefano Zampini   PetscInt          ncc;
3089984c4197SStefano Zampini   /* some quantities */
309045a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3091a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3092984c4197SStefano Zampini 
3093674ae819SStefano Zampini   PetscFunctionBegin;
30948e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
30958e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
30968e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3097088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3098088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
30990e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
31000e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
31010e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
31020e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
31030e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3104088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3105cf5a6209SStefano Zampini 
3106cf5a6209SStefano Zampini   /* print some info */
3107cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
3108cf5a6209SStefano Zampini     IS       vertices;
3109cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
3110cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
3111cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
3112cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
31131575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3114cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3115cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3116fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
3117fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
3118cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
31191575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3120cf5a6209SStefano Zampini   }
3121cf5a6209SStefano Zampini 
3122cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
31239162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3124cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3125cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3126cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3127cf5a6209SStefano Zampini     PetscScalar  *array;
3128cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3129cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3130674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3131b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3132674ae819SStefano Zampini     PetscScalar  *work;
3133674ae819SStefano Zampini     PetscReal    *singular_vals;
3134674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3135674ae819SStefano Zampini     PetscReal    *rwork;
3136674ae819SStefano Zampini #endif
3137674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3138674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3139674ae819SStefano Zampini #else
3140964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3141964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3142674ae819SStefano Zampini #endif
3143674ae819SStefano Zampini 
3144674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3145d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3146d06fc5fdSStefano Zampini     /* free unneeded index sets */
3147d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3148d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3149674ae819SStefano Zampini     }
3150d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3151d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3152d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3153d06fc5fdSStefano Zampini       }
3154d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3155d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3156d06fc5fdSStefano Zampini     }
3157d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3158d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3159d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3160d06fc5fdSStefano Zampini       }
3161d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3162d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3163d06fc5fdSStefano Zampini     }
316470022509SStefano Zampini 
316570022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
316670022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
316770022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
316870022509SStefano Zampini     if (pcbddc->NullSpace) {
316970022509SStefano Zampini       PetscBool tbool[2],gbool[2];
317070022509SStefano Zampini 
317170022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
3172b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
3173d06fc5fdSStefano Zampini         if (!ISForEdges) {
3174d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
3175d06fc5fdSStefano Zampini         }
3176b8ffe317SStefano Zampini       }
3177d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
3178d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
3179d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3180d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
3181d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
318298a51de6SStefano Zampini     }
318370022509SStefano Zampini #endif
318408122e43SStefano Zampini 
3185674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3186674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3187674ae819SStefano Zampini     if (nearnullsp) {
3188674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3189f4ddd8eeSStefano Zampini       /* remove any stored info */
3190f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3191f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3192f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3193f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3194f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3195473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3196f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3197f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3198f4ddd8eeSStefano Zampini       }
3199984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3200984c4197SStefano Zampini       nnsp_size = 0;
3201674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3202674ae819SStefano Zampini     }
3203984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3204984c4197SStefano Zampini     max_constraints = nnsp_size;
3205984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3206984c4197SStefano Zampini 
3207674ae819SStefano Zampini     /*
3208674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
32099162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
32109162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
32119162d606SStefano Zampini          There can be multiple constraints per connected component
3212674ae819SStefano Zampini                                                                                                                                                            */
3213674ae819SStefano Zampini     n_vertices = 0;
3214674ae819SStefano Zampini     if (ISForVertices) {
3215674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3216674ae819SStefano Zampini     }
32179162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
32189162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
32199162d606SStefano Zampini 
32209162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
32219162d606SStefano Zampini     total_counts *= max_constraints;
3222674ae819SStefano Zampini     total_counts += n_vertices;
32234641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
32249162d606SStefano Zampini 
3225674ae819SStefano Zampini     total_counts = 0;
3226674ae819SStefano Zampini     max_size_of_constraint = 0;
3227674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
32289162d606SStefano Zampini       IS used_is;
3229674ae819SStefano Zampini       if (i<n_ISForEdges) {
32309162d606SStefano Zampini         used_is = ISForEdges[i];
3231674ae819SStefano Zampini       } else {
32329162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3233674ae819SStefano Zampini       }
32349162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3235674ae819SStefano Zampini       total_counts += j;
3236674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3237674ae819SStefano Zampini     }
32389162d606SStefano Zampini     ierr = PetscMalloc3(total_counts*max_constraints+n_vertices,&constraints_data,total_counts+n_vertices,&constraints_idxs,total_counts+n_vertices,&constraints_idxs_B);CHKERRQ(ierr);
32399162d606SStefano Zampini 
3240984c4197SStefano Zampini     /* get local part of global near null space vectors */
3241785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3242984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3243984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3244e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3245e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3246984c4197SStefano Zampini     }
3247674ae819SStefano Zampini 
3248242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3249242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3250a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3251242a89d7SStefano Zampini 
3252984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3253a773dcb8SStefano Zampini     if (!skip_lapack) {
3254674ae819SStefano Zampini       PetscScalar temp_work;
3255911cabfeSStefano Zampini 
3256674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3257984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3258785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3259785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3260785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3261674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3262785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3263674ae819SStefano Zampini #endif
3264674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3265c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3266c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3267674ae819SStefano Zampini       lwork = -1;
3268674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3269674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3270c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3271674ae819SStefano Zampini #else
3272c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3273674ae819SStefano Zampini #endif
3274674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3275984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3276674ae819SStefano Zampini #else /* on missing GESVD */
3277674ae819SStefano Zampini       /* SVD */
3278674ae819SStefano Zampini       PetscInt max_n,min_n;
3279674ae819SStefano Zampini       max_n = max_size_of_constraint;
3280984c4197SStefano Zampini       min_n = max_constraints;
3281984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3282674ae819SStefano Zampini         min_n = max_size_of_constraint;
3283984c4197SStefano Zampini         max_n = max_constraints;
3284674ae819SStefano Zampini       }
3285785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3286674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3287785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3288674ae819SStefano Zampini #endif
3289674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3290674ae819SStefano Zampini       lwork = -1;
3291e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3292e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3293b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3294674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3295674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
32969162d606SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&constraints_data[0],&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr));
3297674ae819SStefano Zampini #else
32989162d606SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&constraints_data[0],&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr));
3299674ae819SStefano Zampini #endif
3300674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3301984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3302984c4197SStefano Zampini #endif /* on missing GESVD */
3303674ae819SStefano Zampini       /* Allocate optimal workspace */
3304674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3305854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3306674ae819SStefano Zampini     }
3307674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3308674ae819SStefano Zampini     total_counts = 0;
33099162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
33109162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3311674ae819SStefano Zampini     /* vertices */
33129162d606SStefano Zampini     if (n_vertices) {
3313674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
33149162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3315674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
33169162d606SStefano Zampini         constraints_n[total_counts] = 1;
33179162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
33189162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
33199162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3320674ae819SStefano Zampini         total_counts++;
3321674ae819SStefano Zampini       }
3322674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3323674ae819SStefano Zampini       n_vertices = total_counts;
3324674ae819SStefano Zampini     }
3325984c4197SStefano Zampini 
3326674ae819SStefano Zampini     /* edges and faces */
33279162d606SStefano Zampini     total_counts_cc = total_counts;
3328911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
33299162d606SStefano Zampini       IS        used_is;
33309162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
33319162d606SStefano Zampini 
3332911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
33339162d606SStefano Zampini         used_is = ISForEdges[ncc];
3334984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3335674ae819SStefano Zampini       } else {
33369162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3337984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3338674ae819SStefano Zampini       }
3339674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
33409162d606SStefano Zampini 
33419162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
33429162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3343984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3344984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3345674ae819SStefano Zampini       if (nnsp_has_cnst) {
33465b08dc53SStefano Zampini         PetscScalar quad_value;
33479162d606SStefano Zampini 
33489162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
33499162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
33509162d606SStefano Zampini 
3351a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3352674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3353a773dcb8SStefano Zampini         } else {
3354a773dcb8SStefano Zampini           quad_value = 1.0;
3355a773dcb8SStefano Zampini         }
3356674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
33579162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3358674ae819SStefano Zampini         }
33599162d606SStefano Zampini         temp_constraints++;
3360674ae819SStefano Zampini         total_counts++;
3361674ae819SStefano Zampini       }
3362674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3363984c4197SStefano Zampini         PetscReal real_value;
33649162d606SStefano Zampini         PetscScalar *ptr_to_data;
33659162d606SStefano Zampini 
3366984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
33679162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3368674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
33699162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3370674ae819SStefano Zampini         }
3371984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3372984c4197SStefano Zampini         /* check if array is null on the connected component */
3373e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
33749162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
33755b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3376674ae819SStefano Zampini           temp_constraints++;
3377674ae819SStefano Zampini           total_counts++;
33789162d606SStefano Zampini           if (!idxs_copied) {
33799162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
33809162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3381674ae819SStefano Zampini           }
3382674ae819SStefano Zampini         }
33839162d606SStefano Zampini       }
33849162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
338545a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3386eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3387a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
33889162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
33899162d606SStefano Zampini 
33909162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3391a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
33929162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3393a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
33949162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3395a773dcb8SStefano Zampini         } else { /* perform SVD */
3396984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
33979162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3398674ae819SStefano Zampini 
3399674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3400984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3401984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3402984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3403984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3404984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3405984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3406984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3407984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3408674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3409e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3410984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3411674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3412674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
34139162d606SStefano Zampini               PetscStackCallBLAS("BLASdot",correlation_mat[j*temp_constraints+k] = BLASdot_(&Blas_N,ptr_to_data+k*size_of_constraint,&Blas_one,ptr_to_data+j*size_of_constraint,&Blas_one));
3414674ae819SStefano Zampini             }
3415674ae819SStefano Zampini           }
3416e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3417e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3418e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3419674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3420c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3421674ae819SStefano Zampini #else
3422c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3423674ae819SStefano Zampini #endif
3424674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3425984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3426984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3427674ae819SStefano Zampini           j = 0;
3428984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3429674ae819SStefano Zampini           total_counts = total_counts-j;
343045a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3431e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3432c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3433c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3434c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3435c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3436c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3437c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3438674ae819SStefano Zampini           if (j<temp_constraints) {
3439984c4197SStefano Zampini             PetscInt ii;
3440984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3441674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34429162d606SStefano Zampini             PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,ptr_to_data,&Blas_LDA,correlation_mat,&Blas_LDB,&zero,temp_basis,&Blas_LDC));
3443674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3444984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3445674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
34469162d606SStefano Zampini                 ptr_to_data[k*size_of_constraint+ii] = singular_vals[temp_constraints-1-k]*temp_basis[(temp_constraints-1-k)*size_of_constraint+ii];
3447674ae819SStefano Zampini               }
3448674ae819SStefano Zampini             }
3449674ae819SStefano Zampini           }
3450674ae819SStefano Zampini #else  /* on missing GESVD */
3451e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3452e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3453b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3454674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3455674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
34569162d606SStefano Zampini           PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,ptr_to_data,&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr));
3457674ae819SStefano Zampini #else
34589162d606SStefano Zampini           PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,ptr_to_data,&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr));
3459674ae819SStefano Zampini #endif
3460984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3461674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3462984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3463e310c8b4SStefano Zampini           k = temp_constraints;
3464e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3465674ae819SStefano Zampini           j = 0;
3466e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
346745a1bb75SStefano Zampini           valid_constraints = k-j;
3468911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3469984c4197SStefano Zampini #endif /* on missing GESVD */
3470674ae819SStefano Zampini         }
3471a773dcb8SStefano Zampini       }
34729162d606SStefano Zampini       /* update pointers information */
34739162d606SStefano Zampini       if (valid_constraints) {
34749162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
34759162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
34769162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
34779162d606SStefano Zampini         /* set change_of_basis flag */
347845a1bb75SStefano Zampini         if (boolforchange) {
3479b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
34809162d606SStefano Zampini         }
3481b3d85658SStefano Zampini         total_counts_cc++;
348245a1bb75SStefano Zampini       }
348345a1bb75SStefano Zampini     }
3484984c4197SStefano Zampini     /* free workspace */
34858f1c130eSStefano Zampini     if (!skip_lapack) {
3486984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3487984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3488984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3489984c4197SStefano Zampini #endif
3490984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3491984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3492984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3493984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3494984c4197SStefano Zampini #endif
3495984c4197SStefano Zampini     }
3496984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3497984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3498984c4197SStefano Zampini     }
3499984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3500cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3501cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3502cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3503cf5a6209SStefano Zampini     }
3504cf5a6209SStefano Zampini     if (n_ISForFaces) {
3505cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3506cf5a6209SStefano Zampini     }
3507cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3508cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3509cf5a6209SStefano Zampini     }
3510cf5a6209SStefano Zampini     if (n_ISForEdges) {
3511cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3512cf5a6209SStefano Zampini     }
3513cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
351408122e43SStefano Zampini   } else {
351508122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3516984c4197SStefano Zampini 
351708122e43SStefano Zampini     total_counts = 0;
351808122e43SStefano Zampini     n_vertices = 0;
3519d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3520d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
352108122e43SStefano Zampini     }
352208122e43SStefano Zampini     max_constraints = 0;
35239162d606SStefano Zampini     total_counts_cc = 0;
352408122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
352508122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
35269162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
352708122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
352808122e43SStefano Zampini     }
35299162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
35309162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
35319162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
35329162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
353374d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
35349162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
35359162d606SStefano Zampini     total_counts_cc = 0;
35369162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
35379162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
35389162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
353908122e43SStefano Zampini       }
354008122e43SStefano Zampini     }
35419162d606SStefano Zampini #if 0
35429162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
35439162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
35449162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
35459162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
35469162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
35479162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
35489162d606SStefano Zampini       }
35499162d606SStefano Zampini       printf("\n");
35509162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
35519162d606SStefano Zampini     }
35521b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
35538bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
35541b968477SStefano Zampini     }
35551b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
35568bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] sub %d, edge %d, n %d\n",PetscGlobalRank,i,(PetscBool)PetscBTLookup(sub_schurs->is_edge,i),pcbddc->adaptive_constraints_n[i+n_vertices]);
35571b968477SStefano Zampini     }
355808122e43SStefano Zampini #endif
355908122e43SStefano Zampini 
35608bec7fa6SStefano Zampini     max_size_of_constraint = 0;
35619162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) max_size_of_constraint = PetscMax(max_size_of_constraint,constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i]);
35629162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
356308122e43SStefano Zampini     /* Change of basis */
3564b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
356508122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
356608122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
356708122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3568b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
356908122e43SStefano Zampini         }
357008122e43SStefano Zampini       }
357108122e43SStefano Zampini     }
357208122e43SStefano Zampini   }
3573984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
35744f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
357508122e43SStefano Zampini 
35769162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
35779162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
35789162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
35799162d606SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",constraints_idxs_ptr[total_counts_cc],i);
358008122e43SStefano Zampini   }
3581674ae819SStefano Zampini 
3582674ae819SStefano Zampini   /* Create constraint matrix */
3583674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
358416f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
3585984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
3586984c4197SStefano Zampini 
3587984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
3588a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
3589a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
359074d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
3591984c4197SStefano Zampini   total_primal_vertices=0;
3592b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
35939162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
35949162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3595984c4197SStefano Zampini     if (size_of_constraint == 1) {
35969162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
3597b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
359864efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
35999162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
36009162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
3601a717540cSStefano Zampini       }
3602b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
360374d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
3604a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
3605a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
3606a717540cSStefano Zampini       }
3607fa434743SStefano Zampini     } else {
3608b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
3609fa434743SStefano Zampini     }
3610a717540cSStefano Zampini   }
3611b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
3612b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
3613674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
361470022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3615b3d85658SStefano Zampini 
36164f1b2e48SStefano Zampini   ierr = PetscMalloc2(pcbddc->local_primal_size_cc+pcbddc->benign_n,&pcbddc->local_primal_ref_node,pcbddc->local_primal_size_cc+pcbddc->benign_n,&pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
36170e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
36180e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
3619984c4197SStefano Zampini 
3620984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
362174d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
3622785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
3623984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
362474d5cdf7SStefano Zampini 
3625984c4197SStefano Zampini   j = total_primal_vertices;
362674d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
3627b3d85658SStefano Zampini   cum = total_primal_vertices;
36289162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
36294641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
3630b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
3631b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
3632b3d85658SStefano Zampini       cum++;
36339162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
363474d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
363574d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
363674d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
363774d5cdf7SStefano Zampini       }
36389162d606SStefano Zampini       j += constraints_n[i];
3639674ae819SStefano Zampini     }
3640674ae819SStefano Zampini   }
3641674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
3642674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
3643088faed8SStefano Zampini 
3644674ae819SStefano Zampini   /* set values in constraint matrix */
3645984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
36460e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3647674ae819SStefano Zampini   }
3648984c4197SStefano Zampini   total_counts = total_primal_vertices;
36499162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
36504641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
36519162d606SStefano Zampini       PetscInt *cols;
36529162d606SStefano Zampini 
36539162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
36549162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
36559162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
36569162d606SStefano Zampini         PetscInt    row = total_counts+k;
36579162d606SStefano Zampini         PetscScalar *vals;
36589162d606SStefano Zampini 
36599162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
36609162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
36619162d606SStefano Zampini       }
36629162d606SStefano Zampini       total_counts += constraints_n[i];
3663674ae819SStefano Zampini     }
3664674ae819SStefano Zampini   }
3665674ae819SStefano Zampini   /* assembling */
3666674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3667674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3668088faed8SStefano Zampini 
3669984c4197SStefano Zampini   /*
367045a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3671984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
3672984c4197SStefano Zampini   */
3673674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
3674674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
3675026de310SStefano Zampini     /* dual and primal dofs on a single cc */
3676984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
3677984c4197SStefano Zampini     /* working stuff for GEQRF */
367881d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
3679984c4197SStefano Zampini     PetscBLASInt lqr_work;
3680984c4197SStefano Zampini     /* working stuff for UNGQR */
3681984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
3682984c4197SStefano Zampini     PetscBLASInt lgqr_work;
3683984c4197SStefano Zampini     /* working stuff for TRTRS */
3684984c4197SStefano Zampini     PetscScalar  *trs_rhs;
36853f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
3686984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
3687984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
3688984c4197SStefano Zampini     PetscScalar  *start_vals;
3689984c4197SStefano Zampini     /* working stuff for values insertion */
36904641a718SStefano Zampini     PetscBT      is_primal;
369164efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
3692906d46d4SStefano Zampini     /* matrix sizes */
3693906d46d4SStefano Zampini     PetscInt     global_size,local_size;
3694906d46d4SStefano Zampini     /* temporary change of basis */
3695906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
3696cf5a6209SStefano Zampini     /* extra space for debugging */
3697cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
3698984c4197SStefano Zampini 
3699906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
3700906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
370116f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
3702bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3703906d46d4SStefano Zampini     /* nonzeros for local mat */
3704bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
3705bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
37069162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
3707a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
37089162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3709a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
37109162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
3711a717540cSStefano Zampini         } else {
37129162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
37139162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
3714a717540cSStefano Zampini         }
3715a717540cSStefano Zampini       }
3716a717540cSStefano Zampini     }
3717906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
3718bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3719a717540cSStefano Zampini     /* Set initial identity in the matrix */
3720bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
3721906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3722a717540cSStefano Zampini     }
3723a717540cSStefano Zampini 
3724a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
3725a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3726a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3727a717540cSStefano Zampini     }
3728a717540cSStefano Zampini 
3729a717540cSStefano Zampini 
3730a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
3731a717540cSStefano Zampini     /*
3732a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3733a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3734a717540cSStefano Zampini 
3735a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
3736a717540cSStefano Zampini 
3737a6b551f4SStefano 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)
3738a6b551f4SStefano Zampini 
3739a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
3740a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
3741a717540cSStefano Zampini             |              ...                        |
3742a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
3743a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3744a717540cSStefano Zampini 
3745a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
3746a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3747a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3748a6b551f4SStefano Zampini 
3749a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
3750a717540cSStefano Zampini     */
3751a717540cSStefano Zampini     if (qr_needed) {
3752984c4197SStefano Zampini       /* space to store Q */
3753854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3754984c4197SStefano Zampini       /* first we issue queries for optimal work */
37553f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
37563f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
37573f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3758984c4197SStefano Zampini       lqr_work = -1;
37593f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3760984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3761984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3762785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3763984c4197SStefano Zampini       lgqr_work = -1;
37643f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
37653f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
37663f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
37673f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
37683f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
37693f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3770984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3771984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3772785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3773984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3774785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3775984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3776785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3777a717540cSStefano Zampini       /* allocating workspace for check */
3778a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3779cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3780a717540cSStefano Zampini       }
3781a717540cSStefano Zampini     }
3782984c4197SStefano Zampini     /* array to store whether a node is primal or not */
37834641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3784473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
37850e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
378639e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
378739e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
37884641a718SStefano Zampini     }
378939e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
379039e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
379139e2fb2aSStefano Zampini     }
379239e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3793984c4197SStefano Zampini 
3794a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
37959162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
37969162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
37974641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3798984c4197SStefano Zampini         /* get constraint info */
37999162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3800984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3801984c4197SStefano Zampini 
3802984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
38039162d606SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraints %d: %d need a change of basis (size %d)\n",total_counts,primal_dofs,size_of_constraint);CHKERRQ(ierr);
3804674ae819SStefano Zampini         }
3805984c4197SStefano Zampini 
3806fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3807a717540cSStefano Zampini 
3808a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3809a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
38109162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3811a717540cSStefano Zampini           }
3812984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
38139162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3814984c4197SStefano Zampini 
3815984c4197SStefano Zampini           /* compute QR decomposition of constraints */
38163f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
38173f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
38183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3819674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38203f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3821984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3822674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3823984c4197SStefano Zampini 
3824984c4197SStefano Zampini           /* explictly compute R^-T */
3825984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3826984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
38273f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
38283f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
38293f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
38303f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3831984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38323f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3833984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3834984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3835984c4197SStefano Zampini 
3836a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
38373f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
38383f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
38393f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
38403f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3841984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38423f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3843984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3844984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3845984c4197SStefano Zampini 
3846984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3847984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3848984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
38493f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
38503f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
38513f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
38523f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
38533f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
38543f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3855984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38569162d606SStefano Zampini           PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&zero,constraints_data+constraints_data_ptr[total_counts],&Blas_LDC));
3857984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
38589162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3859984c4197SStefano Zampini 
3860984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
38619162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3862984c4197SStefano Zampini           /* insert cols for primal dofs */
3863984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3864984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
38659162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3866906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3867984c4197SStefano Zampini           }
3868984c4197SStefano Zampini           /* insert cols for dual dofs */
3869984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
38709162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3871984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
38729162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3873906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3874984c4197SStefano Zampini               j++;
3875674ae819SStefano Zampini             }
3876674ae819SStefano Zampini           }
3877984c4197SStefano Zampini 
3878984c4197SStefano Zampini           /* check change of basis */
3879984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3880984c4197SStefano Zampini             PetscInt   ii,jj;
3881984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3882c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3883c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3884c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3885c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3886c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3887c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3888984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3889cf5a6209SStefano Zampini             PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&Blas_M,&Blas_N,&Blas_K,&one,dbg_work,&Blas_LDA,qr_basis,&Blas_LDB,&zero,&dbg_work[size_of_constraint*primal_dofs],&Blas_LDC));
3890984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3891984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3892984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3893cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3894cf5a6209SStefano Zampini                 if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
3895674ae819SStefano Zampini               }
3896674ae819SStefano Zampini             }
3897984c4197SStefano Zampini             if (!valid_qr) {
389822d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3899984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3900984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3901cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3902cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not orthogonal to constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
3903674ae819SStefano Zampini                   }
3904cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3905cf5a6209SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not unitary w.r.t constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
3906984c4197SStefano Zampini                   }
3907984c4197SStefano Zampini                 }
3908984c4197SStefano Zampini               }
3909674ae819SStefano Zampini             } else {
391022d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3911674ae819SStefano Zampini             }
3912674ae819SStefano Zampini           }
3913a717540cSStefano Zampini         } else { /* simple transformation block */
3914a717540cSStefano Zampini           PetscInt    row,col;
3915a6b551f4SStefano Zampini           PetscScalar val,norm;
3916a6b551f4SStefano Zampini 
3917a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39189162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,constraints_data+constraints_data_ptr[total_counts],&Blas_one,constraints_data+constraints_data_ptr[total_counts],&Blas_one));
3919a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
39209162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
39219162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3922bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
39239162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3924906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
39259162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3926a717540cSStefano Zampini             } else {
3927a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
39289162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3929a717540cSStefano Zampini                 if (row != col) {
39309162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3931a717540cSStefano Zampini                 } else {
39329162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3933a717540cSStefano Zampini                 }
3934906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3935a717540cSStefano Zampini               }
3936a717540cSStefano Zampini             }
3937a717540cSStefano Zampini           }
393898a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
393922d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3940a717540cSStefano Zampini           }
3941674ae819SStefano Zampini         }
3942984c4197SStefano Zampini       } else {
3943984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
39449162d606SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %d does not need a change of basis (size %d)\n",total_counts,size_of_constraint);CHKERRQ(ierr);
3945674ae819SStefano Zampini         }
3946674ae819SStefano Zampini       }
3947674ae819SStefano Zampini     }
3948a717540cSStefano Zampini 
3949a717540cSStefano Zampini     /* free workspace */
3950a717540cSStefano Zampini     if (qr_needed) {
3951984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
3952cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3953984c4197SStefano Zampini       }
3954984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3955984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3956984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3957984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3958984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3959674ae819SStefano Zampini     }
3960a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3961906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3962906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3963906d46d4SStefano Zampini 
3964906d46d4SStefano Zampini     /* assembling of global change of variable */
3965bbb9e6c6SStefano Zampini     {
3966bbb9e6c6SStefano Zampini       Mat      tmat;
396716f15bc4SStefano Zampini       PetscInt bs;
396816f15bc4SStefano Zampini 
3969906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3970906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3971bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3972bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3973bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3974bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
397516f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
397616f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3977906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3978bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3979bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3980bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3981bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3982bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3983e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3984e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3985bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3986bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3987906d46d4SStefano Zampini     }
3988906d46d4SStefano Zampini     /* check */
3989906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
3990906d46d4SStefano Zampini       PetscReal error;
3991906d46d4SStefano Zampini       Vec       x,x_change;
3992906d46d4SStefano Zampini 
3993906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3994906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3995906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3996906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3997e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3998e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3999bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4000e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4001e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4002906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4003906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4004906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4005906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4006bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4007906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
4008906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4009906d46d4SStefano Zampini     }
4010b96c3477SStefano Zampini 
4011b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
4012b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
4013b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4014b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
4015ac632422SStefano Zampini         Mat                    S_new,tmat;
4016b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
4017b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
4018b087196eSStefano Zampini         const PetscScalar      *array;
4019b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
4020b087196eSStefano Zampini         PetscInt               i,n_V;
4021bbb9e6c6SStefano Zampini 
4022bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
40236816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4024b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4025b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4026b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4027b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4028bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4029b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4030ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4031b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4032ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4033b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4034b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4035b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4036b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4037b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4038b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
4039b087196eSStefano Zampini           PetscScalar val;
4040b087196eSStefano Zampini           PetscInt    idx;
4041b087196eSStefano Zampini 
4042b087196eSStefano Zampini           idx = idxs_V[i];
4043b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
4044b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4045b087196eSStefano Zampini         }
4046b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4047b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4048ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
4049ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4050ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
4051ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4052b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4053ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4054b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4055ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
4056ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4057ac632422SStefano Zampini         }
4058b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4059b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4060b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4061b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4062b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
4063b96c3477SStefano Zampini       }
4064b96c3477SStefano Zampini     }
4065906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
4066906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
4067b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4068b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4069b9b85e73SStefano Zampini   }
4070906d46d4SStefano Zampini 
4071906d46d4SStefano Zampini   /* set up change of basis context */
4072906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
4073906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
4074906d46d4SStefano Zampini 
4075906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
4076906d46d4SStefano Zampini       PetscInt global_size,local_size;
4077906d46d4SStefano Zampini 
4078906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4079906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4080906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
4081906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4082906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
4083906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
4084906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
4085906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
4086906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
4087906d46d4SStefano Zampini     } else {
4088906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
4089906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
4090906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
4091906d46d4SStefano Zampini     }
4092906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
4093906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4094906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
4095906d46d4SStefano Zampini     } else {
4096906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4097906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
4098906d46d4SStefano Zampini     }
4099906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
4100906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
4101906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4102906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4103a8661815SStefano Zampini   } else {
4104a8661815SStefano Zampini     ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr);
4105b9b85e73SStefano Zampini   }
4106a717540cSStefano Zampini 
41074f1b2e48SStefano Zampini   /* add pressure dofs to set of primal nodes for numbering purposes */
41084f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
41094f1b2e48SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
41104f1b2e48SStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4111019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4112019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
4113019a44ceSStefano Zampini     pcbddc->local_primal_size++;
4114019a44ceSStefano Zampini   }
4115019a44ceSStefano Zampini 
4116019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
4117727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
4118727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
41199f47a83aSStefano Zampini     ierr = PetscMemcmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
4120c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
41210e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
41229f47a83aSStefano Zampini       ierr = PetscMemcmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
4123727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4124727cdba6SStefano Zampini     }
41250e6343abSStefano Zampini   }
41260e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4127727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4128727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4129727cdba6SStefano Zampini 
4130a717540cSStefano Zampini   /* flush dbg viewer */
4131b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4132b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4133b8ffe317SStefano Zampini   }
4134a717540cSStefano Zampini 
4135e310c8b4SStefano Zampini   /* free workspace */
4136a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
41374641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
413808122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
41399162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
41409162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
414108122e43SStefano Zampini   } else {
41429162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
41439162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
41449162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
414508122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
414608122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
41479162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
41489162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
414908122e43SStefano Zampini   }
4150674ae819SStefano Zampini   PetscFunctionReturn(0);
4151674ae819SStefano Zampini }
4152674ae819SStefano Zampini 
4153674ae819SStefano Zampini #undef __FUNCT__
4154674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4155674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4156674ae819SStefano Zampini {
4157674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4158674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4159674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
41607fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
4161674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
4162674ae819SStefano Zampini 
4163674ae819SStefano Zampini   PetscFunctionBegin;
41648e61c736SStefano Zampini   /* Reset previously computed graph */
41658e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4166674ae819SStefano Zampini   /* Init local Graph struct */
41677fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
41683bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4169674ae819SStefano Zampini 
4170575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
41715099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
41725099eff2SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid size of local CSR graph! Found %d, expected %d\n",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
4173575ad6abSStefano Zampini   }
41749577ea80SStefano Zampini 
4175674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
41764d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
41774d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
41784d379d7bSStefano Zampini     PetscInt  nvtxs;
4179e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4180674ae819SStefano Zampini 
41814d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
41822fffb893SStefano Zampini 
41832fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
41842fffb893SStefano Zampini       if (flg_row) {
41854d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4186b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
41872fffb893SStefano Zampini       }
41882fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
41899b28b941SStefano Zampini     } else if (pcbddc->current_level && pcis->n_B) { /* just compute subdomain's connected components for coarser levels when the local boundary is not empty */
41904d379d7bSStefano Zampini       IS                     is_dummy;
41914d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
41924d379d7bSStefano Zampini       PetscInt               j,sum;
41934d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
41944d379d7bSStefano Zampini       const PetscInt         *idxs;
41954d379d7bSStefano Zampini       PCBDDCGraph            graph;
41964d379d7bSStefano Zampini       PetscBT                is_on_boundary;
41974d379d7bSStefano Zampini 
41984d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
41994d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
42004d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
42014d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
42027fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
42034d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
4204e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4205e496cd5dSStefano Zampini       if (flg_row) {
42064d379d7bSStefano Zampini         graph->xadj = xadj;
42074d379d7bSStefano Zampini         graph->adjncy = adjncy;
4208e496cd5dSStefano Zampini       }
42094d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
42104d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4211e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
42124d379d7bSStefano Zampini 
42134d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
42149b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
42154d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
42164d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
42174d379d7bSStefano Zampini         }
42184d379d7bSStefano Zampini       }
42194d379d7bSStefano Zampini 
4220e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
42214d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
42224d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
42234d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
42244d379d7bSStefano Zampini       }
42254d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
42264d379d7bSStefano Zampini 
4227e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
42284d379d7bSStefano Zampini       sum = 0;
42294d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
42304d379d7bSStefano Zampini         PetscInt sizecc = 0;
42314d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
42324d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
42334d379d7bSStefano Zampini             sizecc++;
42344d379d7bSStefano Zampini           }
42354d379d7bSStefano Zampini         }
42364d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
42374d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
42384d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
42394d379d7bSStefano Zampini           }
42404d379d7bSStefano Zampini         }
42414d379d7bSStefano Zampini         sum += sizecc*sizecc;
42424d379d7bSStefano Zampini       }
42434d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
42444d379d7bSStefano Zampini       sum = 0;
4245e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
42464d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
42474d379d7bSStefano Zampini         cxadj[i] = sum;
42484d379d7bSStefano Zampini         sum += temp;
42494d379d7bSStefano Zampini       }
4250e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
42514d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
42524d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
42534d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
42544d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
42554d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
42564d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
42574d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
42584d379d7bSStefano Zampini                 sizecc++;
42594d379d7bSStefano Zampini               }
42604d379d7bSStefano Zampini             }
42614d379d7bSStefano Zampini           }
42624d379d7bSStefano Zampini         }
42634d379d7bSStefano Zampini       }
42649b28b941SStefano Zampini       if (sum) {
4265e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
42664d379d7bSStefano Zampini       } else {
42674d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
42684d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
42694d379d7bSStefano Zampini       }
42704d379d7bSStefano Zampini       graph->xadj = 0;
42714d379d7bSStefano Zampini       graph->adjncy = 0;
42724d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
42734d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
42744d379d7bSStefano Zampini     }
4275674ae819SStefano Zampini   }
42769b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
42779b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4278674ae819SStefano Zampini   }
4279674ae819SStefano Zampini 
428063602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
4281674ae819SStefano Zampini   vertex_size = 1;
428263602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
428363602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
428495ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
428563602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
4286e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
428763602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
4288674ae819SStefano Zampini       }
428963602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
429063602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
429163602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
4292674ae819SStefano Zampini     }
429363602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
4294674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
429563602bcaSStefano Zampini   } else {
429663602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
429763602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
4298854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
429963602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
430063602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
430163602bcaSStefano Zampini       }
430263602bcaSStefano Zampini     }
4303674ae819SStefano Zampini   }
4304674ae819SStefano Zampini 
4305674ae819SStefano Zampini   /* Setup of Graph */
4306785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
4307e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
4308785d1243SStefano Zampini   }
4309785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
4310e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
4311785d1243SStefano Zampini   }
431230368db7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) { /* need to convert from global to local */
431330368db7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
431430368db7SStefano Zampini   }
431530368db7SStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
4316674ae819SStefano Zampini 
43174f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
43184f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
43194f1b2e48SStefano Zampini     PetscInt *local_subs;
43204f1b2e48SStefano Zampini 
43214f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
43224f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
43234f1b2e48SStefano Zampini       const PetscInt *idxs;
43244f1b2e48SStefano Zampini       PetscInt       nl,j;
43254f1b2e48SStefano Zampini 
43264f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
43274f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
43284f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
43294f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
43304f1b2e48SStefano Zampini       }
43314f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
43324f1b2e48SStefano Zampini     }
43334f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
43344f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
43354f1b2e48SStefano Zampini   }
43364f1b2e48SStefano Zampini 
4337674ae819SStefano Zampini   /* Graph's connected components analysis */
4338674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4339674ae819SStefano Zampini 
4340674ae819SStefano Zampini   /* print some info to stdout */
4341674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
4342302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
4343674ae819SStefano Zampini   }
4344fb180af4SStefano Zampini 
4345fb180af4SStefano Zampini   /* mark topography has done */
4346fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
4347674ae819SStefano Zampini   PetscFunctionReturn(0);
4348674ae819SStefano Zampini }
4349674ae819SStefano Zampini 
4350dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4351674ae819SStefano Zampini #undef __FUNCT__
4352674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4353dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4354674ae819SStefano Zampini {
4355dc456d91SStefano Zampini   PetscSF        sf;
4356dc456d91SStefano Zampini   PetscLayout    map;
4357dc456d91SStefano Zampini   const PetscInt *idxs;
4358dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4359dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4360dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4361dc456d91SStefano Zampini   PetscMPIInt    commsize;
4362674ae819SStefano Zampini   PetscBool      first_found;
4363674ae819SStefano Zampini   PetscErrorCode ierr;
4364674ae819SStefano Zampini 
4365674ae819SStefano Zampini   PetscFunctionBegin;
4366dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4367dc456d91SStefano Zampini   if (subset_mult) {
4368dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4369dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4370dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4371674ae819SStefano Zampini   }
4372dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4373dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4374dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4375dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4376dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4377dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4378674ae819SStefano Zampini   }
4379dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4380dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4381dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4382dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4383dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4384dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4385dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4386dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4387dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4388dc456d91SStefano Zampini 
4389dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4390dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4391dc456d91SStefano Zampini   if (subset_mult) {
4392dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4393dc456d91SStefano Zampini 
4394dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4395dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4396dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4397674ae819SStefano Zampini   } else {
4398dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4399674ae819SStefano Zampini   }
4400dc456d91SStefano Zampini   /* local size of new subset */
4401dc456d91SStefano Zampini   n_n = 0;
4402dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4403dc456d91SStefano Zampini 
4404dc456d91SStefano Zampini   /* global indexes in layout */
4405dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4406dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4407dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4408dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4409dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4410dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4411dc456d91SStefano Zampini 
4412dc456d91SStefano Zampini   /* reduce from leaves to roots */
4413dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
441464a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
441564a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4416dc456d91SStefano Zampini 
4417dc456d91SStefano Zampini   /* count indexes in local part of layout */
4418674ae819SStefano Zampini   nlocals = 0;
4419674ae819SStefano Zampini   first_index = -1;
4420674ae819SStefano Zampini   first_found = PETSC_FALSE;
4421dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4422dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4423674ae819SStefano Zampini       first_found = PETSC_TRUE;
4424674ae819SStefano Zampini       first_index = i;
4425674ae819SStefano Zampini     }
4426dc456d91SStefano Zampini     nlocals += root_data[i];
4427674ae819SStefano Zampini   }
4428dc456d91SStefano Zampini 
4429dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
44305fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4431dc456d91SStefano Zampini   start = 0;
443264a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
44335fa240b1SStefano Zampini #else
443464a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
44355fa240b1SStefano Zampini   start = start-nlocals;
44365fa240b1SStefano Zampini #endif
44375fa240b1SStefano Zampini 
4438dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4439dc456d91SStefano Zampini     *N_n = start + nlocals;
4440dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4441dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4442674ae819SStefano Zampini   }
44435fa240b1SStefano Zampini 
44445fa240b1SStefano Zampini   /* adapt root data with cumulative */
4445674ae819SStefano Zampini   if (first_found) {
4446dc456d91SStefano Zampini     PetscInt old_index;
4447dc456d91SStefano Zampini 
4448dc456d91SStefano Zampini     root_data[first_index] += start;
4449674ae819SStefano Zampini     old_index = first_index;
4450dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4451dc456d91SStefano Zampini       if (root_data[i]) {
4452dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4453674ae819SStefano Zampini         old_index = i;
4454674ae819SStefano Zampini       }
4455674ae819SStefano Zampini     }
4456674ae819SStefano Zampini   }
4457dc456d91SStefano Zampini 
4458dc456d91SStefano Zampini   /* from roots to leaves */
4459dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4460dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4461dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4462dc456d91SStefano Zampini 
4463dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4464dc456d91SStefano Zampini   if (subset_mult) {
4465dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4466dc456d91SStefano Zampini     PetscInt        cum;
4467dc456d91SStefano Zampini 
4468dc456d91SStefano Zampini     cum = 0;
4469dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4470dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4471dc456d91SStefano Zampini       PetscInt j;
4472dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4473674ae819SStefano Zampini     }
4474dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4475674ae819SStefano Zampini   } else {
4476dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4477dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4478674ae819SStefano Zampini     }
4479674ae819SStefano Zampini   }
4480dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4481dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4482674ae819SStefano Zampini   PetscFunctionReturn(0);
4483674ae819SStefano Zampini }
44849a7d3425SStefano Zampini 
44859a7d3425SStefano Zampini #undef __FUNCT__
44869a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
44879a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
44889a7d3425SStefano Zampini {
44899a7d3425SStefano Zampini   PetscInt       i,j;
44909a7d3425SStefano Zampini   PetscScalar    *alphas;
44919a7d3425SStefano Zampini   PetscErrorCode ierr;
44929a7d3425SStefano Zampini 
44939a7d3425SStefano Zampini   PetscFunctionBegin;
44949a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4495785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
44969a7d3425SStefano Zampini   for (i=0;i<n;i++) {
44979a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
44989a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
44999a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
45009a7d3425SStefano Zampini   }
45019a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
45029a7d3425SStefano Zampini   PetscFunctionReturn(0);
45039a7d3425SStefano Zampini }
45049a7d3425SStefano Zampini 
4505e7931f94SStefano Zampini #undef __FUNCT__
450670cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
4507b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
4508e7931f94SStefano Zampini {
450952e5ac9dSStefano Zampini   IS             ranks_send_to;
4510e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4511e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
451252e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
451352e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
45143837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
45152b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
4516e7931f94SStefano Zampini   PetscSubcomm   subcomm;
451752e5ac9dSStefano Zampini   PetscErrorCode ierr;
4518a57a6d2fSStefano Zampini 
4519e7931f94SStefano Zampini   PetscFunctionBegin;
45202b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
45212b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
45222b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
4523e7931f94SStefano Zampini 
4524e7931f94SStefano Zampini   /* Get info on mapping */
45253bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
45263bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4527e7931f94SStefano Zampini 
4528e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4529785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4530e7931f94SStefano Zampini   xadj[0] = 0;
4531e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4532785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4533785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
4534e7931f94SStefano Zampini 
45352b510759SStefano Zampini   if (threshold) {
4536d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
45372b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
4538d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
4539d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4540d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4541d023bfaeSStefano Zampini         xadj_count++;
4542e7931f94SStefano Zampini       }
4543e7931f94SStefano Zampini     }
4544d023bfaeSStefano Zampini     xadj[1] = xadj_count;
4545c8587f34SStefano Zampini   } else {
4546e7931f94SStefano Zampini     if (xadj[1]) {
4547e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
4548e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
4549c8587f34SStefano Zampini     }
4550e7931f94SStefano Zampini   }
45513bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4552e7931f94SStefano Zampini   if (use_square) {
4553e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4554e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
4555e7931f94SStefano Zampini     }
4556e7931f94SStefano Zampini   }
4557e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4558e7931f94SStefano Zampini 
45593837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4560e7931f94SStefano Zampini 
4561e7931f94SStefano Zampini   /*
4562e7931f94SStefano Zampini     Restrict work on active processes only.
4563e7931f94SStefano Zampini   */
4564e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
4565e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
4566e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
45672b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
4568d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4569e7931f94SStefano Zampini   if (color) {
4570e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4571e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4572e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4573c8587f34SStefano Zampini   } else {
457452e5ac9dSStefano Zampini     Mat             subdomain_adj;
457552e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
457652e5ac9dSStefano Zampini     MatPartitioning partitioner;
457752e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
457852e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
4579b0c7d250SStefano Zampini     PetscBool       aggregate;
4580b0c7d250SStefano Zampini 
4581306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
4582785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
4583e7931f94SStefano Zampini     prank = rank;
4584306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
45858002ef2cSStefano Zampini     /*
4586e7931f94SStefano Zampini     for (i=0;i<size;i++) {
4587e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
4588c8587f34SStefano Zampini     }
45898002ef2cSStefano Zampini     */
4590e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4591e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4592c8587f34SStefano Zampini     }
4593e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4594b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
4595b0c7d250SStefano Zampini     if (aggregate) {
4596b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
4597b0c7d250SStefano Zampini       PetscMPIInt nrank;
4598b0c7d250SStefano Zampini       PetscScalar *vals;
4599b0c7d250SStefano Zampini 
4600b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
4601b0c7d250SStefano Zampini       lrows = 0;
4602b0c7d250SStefano Zampini       if (nrank<redprocs) {
4603b0c7d250SStefano Zampini         lrows = size/redprocs;
4604b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
4605b0c7d250SStefano Zampini       }
46065fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
4607b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
4608b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4609b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4610b0c7d250SStefano Zampini       row = nrank;
4611b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
4612b0c7d250SStefano Zampini       cols = adjncy;
4613b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
4614b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
4615b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
4616b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4617b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
461852e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
461952e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
462052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4621b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
4622b0c7d250SStefano Zampini     } else {
4623306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
4624b0c7d250SStefano Zampini     }
462522b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
4626e7931f94SStefano Zampini 
4627e7931f94SStefano Zampini     /* Partition */
4628306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
4629e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
4630e7931f94SStefano Zampini     if (use_vwgt) {
46313837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
4632e7931f94SStefano Zampini       v_wgt[0] = local_size;
4633e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
4634c8587f34SStefano Zampini     }
463528143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
463628143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
4637e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
4638e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
463922b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
4640e7931f94SStefano Zampini 
464152e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
464252e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
464352e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
464452e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4645b0c7d250SStefano Zampini     if (!redprocs) {
4646b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
464728143c3dSStefano Zampini     } else {
4648b0c7d250SStefano Zampini       PetscInt    idxs[1];
4649b0c7d250SStefano Zampini       PetscMPIInt tag;
4650b0c7d250SStefano Zampini       MPI_Request *reqs;
4651b0c7d250SStefano Zampini 
4652b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
4653b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
4654b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
4655b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
465628143c3dSStefano Zampini       }
4657b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
4658b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4659b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
4660b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
4661e7931f94SStefano Zampini     }
466252e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4663e7931f94SStefano Zampini     /* clean up */
4664e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
466552e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
4666e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
4667e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
4668e7931f94SStefano Zampini   }
4669e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
4670e7931f94SStefano Zampini 
4671e7931f94SStefano Zampini   /* assemble parallel IS for sends */
4672e7931f94SStefano Zampini   i = 1;
4673e7931f94SStefano Zampini   if (color) i=0;
4674e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
4675e7931f94SStefano Zampini   /* get back IS */
4676e7931f94SStefano Zampini   *is_sends = ranks_send_to;
4677e7931f94SStefano Zampini   PetscFunctionReturn(0);
4678e7931f94SStefano Zampini }
4679e7931f94SStefano Zampini 
4680e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
4681e7931f94SStefano Zampini 
4682e7931f94SStefano Zampini #undef __FUNCT__
4683e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
468453a05cb3SStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, PetscBool restrict_full, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
4685e7931f94SStefano Zampini {
468670cf5478SStefano Zampini   Mat                    local_mat;
4687e7931f94SStefano Zampini   IS                     is_sends_internal;
46889d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
468928143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
46909d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
4691e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
4692e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
4693e7931f94SStefano Zampini   const PetscInt*        is_indices;
4694e7931f94SStefano Zampini   MatType                new_local_type;
4695e7931f94SStefano Zampini   /* buffers */
4696e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
469728143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
46989d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
4699e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
4700e7931f94SStefano Zampini   /* MPI */
470128143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
470228143c3dSStefano Zampini   PetscSubcomm           subcomm;
4703e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
470428143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
470528143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
470628143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
470728143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
470828143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
4709e7931f94SStefano Zampini   PetscErrorCode         ierr;
4710e7931f94SStefano Zampini 
4711e7931f94SStefano Zampini   PetscFunctionBegin;
471228143c3dSStefano Zampini   /* TODO: add missing checks */
471328143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
471428143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
471528143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
471628143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
4717e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
471828143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
4719e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4720e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
4721e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
4722e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
4723e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
472428143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
472570cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
472670cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
472728143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
472870cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
472970cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
473070cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
473170cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
473270cf5478SStefano Zampini   }
4733e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
4734e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
4735e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
4736e7931f94SStefano Zampini   if (!is_sends) {
473728143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
4738b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
4739c8587f34SStefano Zampini   } else {
4740e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
4741e7931f94SStefano Zampini     is_sends_internal = is_sends;
4742c8587f34SStefano Zampini   }
4743e7931f94SStefano Zampini 
4744e7931f94SStefano Zampini   /* get comm */
4745a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4746e7931f94SStefano Zampini 
4747e7931f94SStefano Zampini   /* compute number of sends */
4748e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4749e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4750e7931f94SStefano Zampini 
4751e7931f94SStefano Zampini   /* compute number of receives */
4752e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4753785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4754e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4755e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4756e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4757e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4758e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
4759e7931f94SStefano Zampini 
476028143c3dSStefano Zampini   /* restrict comm if requested */
476128143c3dSStefano Zampini   subcomm = 0;
476228143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
476328143c3dSStefano Zampini   if (restrict_comm) {
4764779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
4765779c1cceSStefano Zampini 
476628143c3dSStefano Zampini     color = 0;
476753a05cb3SStefano Zampini     if (restrict_full) {
476853a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
476953a05cb3SStefano Zampini     } else {
477053a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
477153a05cb3SStefano Zampini     }
477228143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
477328143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
477428143c3dSStefano Zampini     /* check if reuse has been requested */
477528143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
477628143c3dSStefano Zampini       if (*mat_n) {
477728143c3dSStefano Zampini         PetscMPIInt subcommsize2;
477828143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
477928143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
478028143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
478128143c3dSStefano Zampini       } else {
478228143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
478328143c3dSStefano Zampini       }
478428143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
4785779c1cceSStefano Zampini       PetscMPIInt rank;
4786779c1cceSStefano Zampini 
4787779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
478828143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
478928143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
479028143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4791306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
479228143c3dSStefano Zampini     }
479328143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
479428143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
479528143c3dSStefano Zampini   } else {
479628143c3dSStefano Zampini     comm_n = comm;
479728143c3dSStefano Zampini   }
479828143c3dSStefano Zampini 
4799e7931f94SStefano Zampini   /* prepare send/receive buffers */
4800785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4801e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4802785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4803e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
480428143c3dSStefano Zampini   if (nis) {
4805854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
480628143c3dSStefano Zampini   }
4807e7931f94SStefano Zampini 
480828143c3dSStefano Zampini   /* Get data from local matrices */
4809e7931f94SStefano Zampini   if (!isdense) {
4810a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4811e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4812e7931f94SStefano Zampini     /*
4813e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4814e7931f94SStefano Zampini        send_buffer_idxs should contain:
4815e7931f94SStefano Zampini        - MatType_PRIVATE type
4816e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4817e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4818e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4819e7931f94SStefano Zampini     */
4820e7931f94SStefano Zampini   } else {
4821e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
48223bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4823854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4824e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4825e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
48263bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4827e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
48283bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4829e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4830e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4831e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4832e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4833c8587f34SStefano Zampini     }
4834c8587f34SStefano Zampini   }
4835e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
483628143c3dSStefano Zampini   /* additional is (if any) */
483728143c3dSStefano Zampini   if (nis) {
483828143c3dSStefano Zampini     PetscMPIInt psum;
483928143c3dSStefano Zampini     PetscInt j;
484028143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
484128143c3dSStefano Zampini       PetscInt plen;
484228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
484328143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
484428143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
484528143c3dSStefano Zampini     }
4846854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
484728143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
484828143c3dSStefano Zampini       PetscInt plen;
484928143c3dSStefano Zampini       const PetscInt *is_array_idxs;
485028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
485128143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
485228143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
485328143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
485428143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
485528143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
485628143c3dSStefano Zampini     }
485728143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
485828143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
485928143c3dSStefano Zampini     }
486028143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
486128143c3dSStefano Zampini   }
486228143c3dSStefano Zampini 
4863e7931f94SStefano Zampini   buf_size_idxs = 0;
4864e7931f94SStefano Zampini   buf_size_vals = 0;
486528143c3dSStefano Zampini   buf_size_idxs_is = 0;
4866e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4867e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4868e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
486928143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4870e7931f94SStefano Zampini   }
4871785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4872785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
487395ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4874e7931f94SStefano Zampini 
4875e7931f94SStefano Zampini   /* get new tags for clean communications */
4876e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4877e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
487828143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4879e7931f94SStefano Zampini 
4880e7931f94SStefano Zampini   /* allocate for requests */
4881785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4882785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
488395ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4884785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4885785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
488695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4887e7931f94SStefano Zampini 
4888e7931f94SStefano Zampini   /* communications */
4889e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4890e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
489128143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4892e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4893e7931f94SStefano Zampini     source_dest = onodes[i];
4894e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4895e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4896e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4897e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
489828143c3dSStefano Zampini     if (nis) {
489928143c3dSStefano 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);
490028143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
490128143c3dSStefano Zampini     }
4902e7931f94SStefano Zampini   }
4903e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4904e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4905e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4906e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
490728143c3dSStefano Zampini     if (nis) {
490828143c3dSStefano 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);
490928143c3dSStefano Zampini     }
4910e7931f94SStefano Zampini   }
4911e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4912e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4913e7931f94SStefano Zampini 
4914e7931f94SStefano Zampini   /* assemble new l2g map */
4915e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4916e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
49179d30be91SStefano Zampini   new_local_rows = 0;
4918e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
49199d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4920e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4921e7931f94SStefano Zampini   }
49229d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4923e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
49249d30be91SStefano Zampini   new_local_rows = 0;
4925e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
49269d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
49279d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4928e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4929e7931f94SStefano Zampini   }
49309d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
49319d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4932e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4933e7931f94SStefano Zampini 
4934e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4935e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4936e7931f94SStefano 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) */
4937e7931f94SStefano Zampini   if (n_recvs) {
493828143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4939e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4940e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4941e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4942e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4943e7931f94SStefano Zampini         break;
4944e7931f94SStefano Zampini       }
4945e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4946e7931f94SStefano Zampini     }
4947e7931f94SStefano Zampini     switch (new_local_type_private) {
494828143c3dSStefano Zampini       case MATDENSE_PRIVATE:
494928143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4950e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4951e7931f94SStefano Zampini           bs = 1;
495228143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
495328143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
495428143c3dSStefano Zampini           bs = 1;
495528143c3dSStefano Zampini         }
4956e7931f94SStefano Zampini         break;
4957e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4958e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4959e7931f94SStefano Zampini         bs = 1;
4960e7931f94SStefano Zampini         break;
4961e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4962e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4963e7931f94SStefano Zampini         break;
4964e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4965e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4966e7931f94SStefano Zampini         break;
4967e7931f94SStefano Zampini       default:
49689d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4969e7931f94SStefano Zampini         break;
4970e7931f94SStefano Zampini     }
497128143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
497228143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
497328143c3dSStefano Zampini     bs = 1;
4974e7931f94SStefano Zampini   }
4975e7931f94SStefano Zampini 
497670cf5478SStefano Zampini   /* create MATIS object if needed */
497770cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4978e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4979e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
498070cf5478SStefano Zampini   } else {
498170cf5478SStefano Zampini     /* it also destroys the local matrices */
498270cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
498370cf5478SStefano Zampini   }
498470cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4985e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
49869d30be91SStefano Zampini 
49879d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
49889d30be91SStefano Zampini 
49899d30be91SStefano Zampini   /* Global to local map of received indices */
49909d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
49919d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
49929d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
49939d30be91SStefano Zampini 
49949d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
49959d30be91SStefano Zampini   buf_size_idxs = 0;
49969d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
49979d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
49989d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
49999d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
50009d30be91SStefano Zampini   }
50019d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
50029d30be91SStefano Zampini 
50039d30be91SStefano Zampini   /* set preallocation */
50049d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
50059d30be91SStefano Zampini   if (!newisdense) {
50069d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
50079d30be91SStefano Zampini 
50089d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
50099d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
50109d30be91SStefano Zampini     if (n_recvs) {
50119d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
50129d30be91SStefano Zampini     }
50139d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
50149d30be91SStefano Zampini       PetscInt j;
50159d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
50169d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
50179d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
50189d30be91SStefano Zampini         }
50199d30be91SStefano Zampini       } else {
50209d30be91SStefano Zampini         /* TODO */
50219d30be91SStefano Zampini       }
50229d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
50239d30be91SStefano Zampini     }
50249d30be91SStefano Zampini     if (new_local_nnz) {
50259d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
50269d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
50279d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
50289d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
50299d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
50309d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
50319d30be91SStefano Zampini     } else {
50329d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
50339d30be91SStefano Zampini     }
50349d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
50359d30be91SStefano Zampini   } else {
50369d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
50379d30be91SStefano Zampini   }
5038e7931f94SStefano Zampini 
5039e7931f94SStefano Zampini   /* set values */
5040e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
50419d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5042e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5043e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5044e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
50459d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5046e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5047e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5048e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
504928143c3dSStefano Zampini     } else {
505028143c3dSStefano Zampini       /* TODO */
5051e7931f94SStefano Zampini     }
5052e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5053e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5054e7931f94SStefano Zampini   }
5055e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5056e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
505770cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
505870cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
50599d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
50609d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5061e7931f94SStefano Zampini 
5062dfd14d43SStefano Zampini #if 0
506328143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5064e7931f94SStefano Zampini     Vec       lvec,rvec;
5065e7931f94SStefano Zampini     PetscReal infty_error;
5066e7931f94SStefano Zampini 
50672a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5068e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5069e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5070e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
507170cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5072e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5073e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5074e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5075e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5076e7931f94SStefano Zampini   }
507728143c3dSStefano Zampini #endif
5078e7931f94SStefano Zampini 
507928143c3dSStefano Zampini   /* assemble new additional is (if any) */
508028143c3dSStefano Zampini   if (nis) {
508128143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
508228143c3dSStefano Zampini 
508328143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5084854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
508528143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
508628143c3dSStefano Zampini     psum = 0;
508728143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
508828143c3dSStefano Zampini       for (j=0;j<nis;j++) {
508928143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
509028143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
509128143c3dSStefano Zampini         psum += plen;
509228143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
509328143c3dSStefano Zampini       }
509428143c3dSStefano Zampini     }
5095854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5096854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
509728143c3dSStefano Zampini     for (i=1;i<nis;i++) {
509828143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
509928143c3dSStefano Zampini     }
510028143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
510128143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
510228143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
510328143c3dSStefano Zampini       for (j=0;j<nis;j++) {
510428143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
510528143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
510628143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
510728143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
510828143c3dSStefano Zampini       }
510928143c3dSStefano Zampini     }
511028143c3dSStefano Zampini     for (i=0;i<nis;i++) {
511128143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
511228143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
511328143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
511428143c3dSStefano Zampini     }
511528143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
511628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
511728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
511828143c3dSStefano Zampini   }
5119e7931f94SStefano Zampini   /* free workspace */
512028143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5121e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5122e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5123e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5124e7931f94SStefano Zampini   if (isdense) {
5125e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5126e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5127e7931f94SStefano Zampini   } else {
5128e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5129e7931f94SStefano Zampini   }
513028143c3dSStefano Zampini   if (nis) {
513128143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
513228143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
513328143c3dSStefano Zampini   }
5134e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5135e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
513628143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5137e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5138e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
513928143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5140e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5141e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5142e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5143e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5144e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
514528143c3dSStefano Zampini   if (nis) {
514628143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
514728143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
514828143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
514928143c3dSStefano Zampini   }
515028143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
515128143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
515228143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
515328143c3dSStefano Zampini     for (i=0;i<nis;i++) {
515428143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
515528143c3dSStefano Zampini     }
515653a05cb3SStefano Zampini     *mat_n = NULL;
515728143c3dSStefano Zampini   }
5158e7931f94SStefano Zampini   PetscFunctionReturn(0);
5159e7931f94SStefano Zampini }
5160a57a6d2fSStefano Zampini 
516112edc857SStefano Zampini /* temporary hack into ksp private data structure */
5162af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
516312edc857SStefano Zampini 
5164c8587f34SStefano Zampini #undef __FUNCT__
5165c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5166c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5167c8587f34SStefano Zampini {
5168c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5169c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
517020a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
51719881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
517220a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
51736e683305SStefano Zampini   IS                     coarse_is,*isarray;
51746e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
517530368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5176f9eb5b7dSStefano Zampini   PC                     pc_temp;
5177c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5178c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5179f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
51804f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
51816e683305SStefano Zampini   Mat                    t_coarse_mat_is;
51826e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
51836e683305SStefano Zampini   PetscMPIInt            all_procs;
518474e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
518568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
518622bc73bbSStefano Zampini   PetscScalar            *array;
51879881197aSStefano Zampini   PetscErrorCode         ierr;
5188fdc09c96SStefano Zampini 
5189c8587f34SStefano Zampini   PetscFunctionBegin;
5190c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
519168457ee5SStefano 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 */
5192fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
51935a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5194fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5195f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5196f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5197f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5198fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
519951bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
520051bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5201dc4bcba2SStefano Zampini         PC        pc;
5202dc4bcba2SStefano Zampini         PetscBool isbddc;
5203dc4bcba2SStefano Zampini 
5204dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5205dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5206dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5207dc4bcba2SStefano Zampini         if (isbddc) {
5208dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
5209dc4bcba2SStefano Zampini         }
5210727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
5211fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5212fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5213fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5214f4ddd8eeSStefano Zampini       }
5215fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5216fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5217f4ddd8eeSStefano Zampini     }
521870cf5478SStefano Zampini     /* reset any subassembling information */
521970cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
52206e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
52216e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5222fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5223f4ddd8eeSStefano Zampini   }
5224c8587f34SStefano Zampini 
52256e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
52262b510759SStefano Zampini   im_active = !!(pcis->n);
52272b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
52286e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
52296e683305SStefano Zampini   void_procs = all_procs-active_procs;
52306e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
523174e2c79eSStefano Zampini   redist = PETSC_FALSE;
523222bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
52336e683305SStefano Zampini     csin_ml = PETSC_TRUE;
52346e683305SStefano Zampini     ncoarse_ml = void_procs;
5235779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
5236779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
52376e683305SStefano Zampini       csin_ds = PETSC_TRUE;
523818a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
523918a45a71SStefano Zampini       redist = PETSC_TRUE;
524018a45a71SStefano Zampini     } else {
52416e683305SStefano Zampini       csin_ds = PETSC_TRUE;
5242779c1cceSStefano Zampini       ncoarse_ds = active_procs;
5243779c1cceSStefano Zampini       redist = PETSC_TRUE;
524418a45a71SStefano Zampini     }
52456e683305SStefano Zampini   } else {
52466e683305SStefano Zampini     csin_ml = PETSC_FALSE;
52476e683305SStefano Zampini     ncoarse_ml = all_procs;
52486e683305SStefano Zampini     if (void_procs) {
52496e683305SStefano Zampini       csin_ds = PETSC_TRUE;
52506e683305SStefano Zampini       ncoarse_ds = void_procs;
52516e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
52526e683305SStefano Zampini     } else {
5253779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
525474e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
525574e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
525674e2c79eSStefano Zampini         redist = PETSC_TRUE;
525774e2c79eSStefano Zampini       } else {
52586e683305SStefano Zampini         csin_ds = PETSC_FALSE;
52596e683305SStefano Zampini         ncoarse_ds = all_procs;
52606e683305SStefano Zampini       }
52616e683305SStefano Zampini     }
526274e2c79eSStefano Zampini   }
52636e683305SStefano Zampini 
52646e683305SStefano Zampini   /*
52656e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
52666e683305SStefano Zampini     - we have not exceeded the number of levels requested
52676e683305SStefano Zampini     - we can actually subassemble the active processes
52686e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
52696e683305SStefano Zampini   */
52706e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
52716e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
52726e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
52736e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
52746e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
5275f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
52762b510759SStefano Zampini     } else {
5277f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
5278c8587f34SStefano Zampini     }
5279c8587f34SStefano Zampini   }
52806e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
52816e683305SStefano Zampini   if (multilevel_allowed) {
52826e683305SStefano Zampini     ncoarse = ncoarse_ml;
52836e683305SStefano Zampini     csin = csin_ml;
528458da7f69SStefano Zampini     redist = PETSC_FALSE;
52856e683305SStefano Zampini   } else {
52866e683305SStefano Zampini     ncoarse = ncoarse_ds;
52876e683305SStefano Zampini     csin = csin_ds;
52886e683305SStefano Zampini   }
5289e7931f94SStefano Zampini 
5290abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5291abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5292abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5293abbbba34SStefano Zampini 
5294abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
529522bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
529622bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
529722bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
529822bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5299e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)pc),1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_islg,NULL,&t_coarse_mat_is);CHKERRQ(ierr);
53006e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
53016e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
53026e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5303abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5304abbbba34SStefano Zampini 
53056e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
530630368db7SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local))) { /* protects from unneded computations */
53076e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
53086e683305SStefano Zampini     const PetscInt         *idxs;
53096e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
53106e683305SStefano Zampini 
53116e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
53120be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
53136e683305SStefano Zampini     /* allocate space for temporary storage */
5314854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5315854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
53166e683305SStefano Zampini     /* allocate for IS array */
53176e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
53186e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
531930368db7SStefano Zampini     nisvert = 0;
532030368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
532130368db7SStefano Zampini       nisvert = 1;
532230368db7SStefano Zampini     }
532330368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5324854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
53256e683305SStefano Zampini     /* dofs splitting */
53266e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
53276e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
53286e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
53296e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
53306e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
53316e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
53326e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
533330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
53346e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
53356e683305SStefano Zampini     }
53366e683305SStefano Zampini     /* neumann boundaries */
53376e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
53386e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
53396e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
53406e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
53416e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
53426e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
53436e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
534430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
53456e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
53466e683305SStefano Zampini     }
534730368db7SStefano Zampini     /* primal vertices (benign) */
534830368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
534930368db7SStefano Zampini       ierr = ISGetLocalSize(pcbddc->user_primal_vertices_local,&tsize);CHKERRQ(ierr);
535030368db7SStefano Zampini       ierr = ISGetIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
535130368db7SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
535230368db7SStefano Zampini       ierr = ISRestoreIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
535330368db7SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
535430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nis-1]);CHKERRQ(ierr);
535530368db7SStefano Zampini     }
53566e683305SStefano Zampini     /* free memory */
53576e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
53586e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
53596e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
53606e683305SStefano Zampini   } else {
53616e683305SStefano Zampini     nis = 0;
53626e683305SStefano Zampini     nisdofs = 0;
53636e683305SStefano Zampini     nisneu = 0;
536430368db7SStefano Zampini     nisvert = 0;
53656e683305SStefano Zampini     isarray = NULL;
53666e683305SStefano Zampini   }
53676e683305SStefano Zampini   /* destroy no longer needed map */
53686e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
53696e683305SStefano Zampini 
53706e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
53716e683305SStefano Zampini   coarse_mat_is = NULL;
53726e683305SStefano Zampini   if (csin) {
53736e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
537474e2c79eSStefano Zampini       if (redist) {
537574e2c79eSStefano Zampini         PetscMPIInt rank;
5376779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
537774e2c79eSStefano Zampini 
537874e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
537958da7f69SStefano Zampini         spc = active_procs/ncoarse;
538058da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
5381779c1cceSStefano Zampini         if (im_active) {
5382779c1cceSStefano Zampini           destsize = 1;
538374e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
538474e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
538574e2c79eSStefano Zampini           } else {
538674e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
538774e2c79eSStefano Zampini           }
538874e2c79eSStefano Zampini         } else {
5389779c1cceSStefano Zampini           destsize = 0;
53906e683305SStefano Zampini         }
5391779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5392779c1cceSStefano Zampini       } else if (csin_type_simple) {
53936e683305SStefano Zampini         PetscMPIInt rank;
53946e683305SStefano Zampini         PetscInt    issize,isidx;
5395779c1cceSStefano Zampini 
53966e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
53976e683305SStefano Zampini         if (im_active) {
53986e683305SStefano Zampini           issize = 1;
53996e683305SStefano Zampini           isidx = (PetscInt)rank;
54006e683305SStefano Zampini         } else {
54016e683305SStefano Zampini           issize = 0;
54026e683305SStefano Zampini           isidx = -1;
54036e683305SStefano Zampini         }
54046e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5405779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
5406b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
54076e683305SStefano Zampini       }
5408779c1cceSStefano Zampini 
5409779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
5410779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
5411779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
5412779c1cceSStefano Zampini         PetscInt *coarse_candidates;
5413779c1cceSStefano Zampini         const PetscInt* tisindices;
5414779c1cceSStefano Zampini 
5415779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
5416779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
5417779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5418779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
5419779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
5420779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
5421779c1cceSStefano Zampini           }
5422779c1cceSStefano Zampini         }
5423779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
5424779c1cceSStefano Zampini 
5425779c1cceSStefano Zampini 
54266e683305SStefano Zampini         if (pcbddc->dbg_flag) {
54276e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54286e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
54296e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
54306e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
5431779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
54326e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
54336e683305SStefano Zampini           }
54346e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
54356e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54366e683305SStefano Zampini         }
54376e683305SStefano Zampini         /* shift the pattern on coarse candidates */
54386e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
54396e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
5440854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
54416e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
54426e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
54436e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
54446e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
54456e683305SStefano Zampini       }
54466e683305SStefano Zampini       if (pcbddc->dbg_flag) {
54476e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54486e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
54496e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
54506e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54516e683305SStefano Zampini       }
5452779c1cceSStefano Zampini     }
54536e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
545453a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
545553a05cb3SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,PETSC_FALSE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
545653a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
545753a05cb3SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
545853a05cb3SStefano Zampini     }
54596e683305SStefano Zampini   } else {
54606e683305SStefano Zampini     if (pcbddc->dbg_flag) {
54616e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54626e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
54636e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54646e683305SStefano Zampini     }
54656e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
54666e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
54676e683305SStefano Zampini   }
54686e683305SStefano Zampini 
54696e683305SStefano Zampini   /* create local to global scatters for coarse problem */
547068457ee5SStefano Zampini   if (compute_vecs) {
54716e683305SStefano Zampini     PetscInt lrows;
54726e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
54736e683305SStefano Zampini     if (coarse_mat_is) {
54746e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
54756e683305SStefano Zampini     } else {
54766e683305SStefano Zampini       lrows = 0;
54776e683305SStefano Zampini     }
54786e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
54796e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
54806e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
54816e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
54826e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
54836e683305SStefano Zampini   }
54846e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
54856e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
5486c8587f34SStefano Zampini 
5487f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5488f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5489f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5490f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5491f9eb5b7dSStefano Zampini   } else {
5492f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5493f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5494c8587f34SStefano Zampini   }
5495c8587f34SStefano Zampini 
54966e683305SStefano Zampini   /* print some info if requested */
54976e683305SStefano Zampini   if (pcbddc->dbg_flag) {
54986e683305SStefano Zampini     if (!multilevel_allowed) {
54996e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
55006e683305SStefano Zampini       if (multilevel_requested) {
55016e683305SStefano 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);
55026e683305SStefano Zampini       } else if (pcbddc->max_levels) {
55036e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
55046e683305SStefano Zampini       }
55056e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
55066e683305SStefano Zampini     }
55076e683305SStefano Zampini   }
55086e683305SStefano Zampini 
5509f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
55106e683305SStefano Zampini   if (coarse_mat_is) {
55116e683305SStefano Zampini     MatReuse coarse_mat_reuse;
55126a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
55136e683305SStefano Zampini     if (pcbddc->dbg_flag) {
55146e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
55156e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
55166e683305SStefano Zampini     }
5517f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5518312be037SStefano Zampini       char prefix[256],str_level[16];
5519e604994aSStefano Zampini       size_t len;
55206e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5521422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5522c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5523f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
55245f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
5525c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
55266e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5527c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5528c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5529e604994aSStefano Zampini       /* prefix */
5530e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5531e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5532e604994aSStefano Zampini       if (!pcbddc->current_level) {
5533e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5534e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5535c8587f34SStefano Zampini       } else {
5536e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5537312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5538312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
553934d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5540312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5541e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5542e604994aSStefano Zampini       }
5543e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
55443e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
55453e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
55463e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
55473e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5548f9eb5b7dSStefano Zampini       /* allow user customization */
5549f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
55503e3c6dadSStefano Zampini     }
55513e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
555251bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
55533e3c6dadSStefano Zampini     if (nisdofs) {
55543e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
55553e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
55563e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
55573e3c6dadSStefano Zampini       }
55583e3c6dadSStefano Zampini     }
55593e3c6dadSStefano Zampini     if (nisneu) {
55603e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
55613e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5562312be037SStefano Zampini     }
556330368db7SStefano Zampini     if (nisvert) {
556430368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
556530368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
556630368db7SStefano Zampini     }
5567f9eb5b7dSStefano Zampini 
5568f9eb5b7dSStefano Zampini     /* get some info after set from options */
5569f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5570f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
55714f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
55726e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5573f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5574f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5575f9eb5b7dSStefano Zampini     }
557639f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
55774f3a063dSStefano Zampini     if (isredundant) {
55784f3a063dSStefano Zampini       KSP inner_ksp;
55794f3a063dSStefano Zampini       PC  inner_pc;
55804f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
55814f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
55824f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
55834f3a063dSStefano Zampini     }
5584f9eb5b7dSStefano Zampini 
5585f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
5586fa7f1dd8SStefano Zampini     if (coarse_reuse) {
558781d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
5588fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
55896e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
5590fa7f1dd8SStefano Zampini     } else {
55916e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
5592fa7f1dd8SStefano Zampini     }
5593c8587f34SStefano Zampini     if (isbddc || isnn) {
559422bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
559570cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
5596b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
559722b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
55986e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
55996e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
56006e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
56016e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
560222b6e8a2SStefano Zampini           }
560370cf5478SStefano Zampini         }
560453a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
560570cf5478SStefano Zampini       } else {
560622bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
560722bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
560822bc73bbSStefano Zampini       }
560922bc73bbSStefano Zampini     } else {
56102e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
5611c8587f34SStefano Zampini     }
5612c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
5613c8587f34SStefano Zampini 
56143301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
56155a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
56163301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
56173301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
56183301b35fSStefano Zampini     }
56193301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
56203301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
56213301b35fSStefano Zampini     }
56223301b35fSStefano Zampini     if (pc->pmat->spd_set) {
56233301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
56243301b35fSStefano Zampini     }
56256e683305SStefano Zampini     /* set operators */
56265f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
56276e683305SStefano Zampini     if (pcbddc->dbg_flag) {
56286e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
56296e683305SStefano Zampini     }
56306e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
56316e683305SStefano Zampini     coarse_mat = 0;
56326e683305SStefano Zampini   }
56336e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
5634b1ecc7b1SStefano Zampini #if 0
5635b9b85e73SStefano Zampini   {
5636b9b85e73SStefano Zampini     PetscViewer viewer;
5637b9b85e73SStefano Zampini     char filename[256];
5638b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
5639b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
5640b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5641b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
5642b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5643b9b85e73SStefano Zampini   }
5644b9b85e73SStefano Zampini #endif
5645c8587f34SStefano Zampini 
5646c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
5647298c0119SStefano Zampini #if 0
5648c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
5649c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
565098a51de6SStefano Zampini   }
5651298c0119SStefano Zampini #endif
5652b0f5fe93SStefano Zampini   /* hack */
565398a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
565498a51de6SStefano Zampini     Vec crhs,csol;
565504708bb6SStefano Zampini 
5656f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
5657f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
5658f347579bSStefano Zampini     if (!csol) {
56592a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
5660f9eb5b7dSStefano Zampini     }
5661f347579bSStefano Zampini     if (!crhs) {
56622a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
5663f347579bSStefano Zampini     }
5664b0f5fe93SStefano Zampini   }
5665b0f5fe93SStefano Zampini 
5666b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
5667b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
5668b0f5fe93SStefano Zampini 
5669b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
56704f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
56714f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
56724f1b2e48SStefano Zampini     }
5673b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
5674b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
5675b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5676b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5677b0f5fe93SStefano Zampini     if (coarse_mat) {
5678b0f5fe93SStefano Zampini       Vec         nullv;
5679b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
5680b0f5fe93SStefano Zampini       PetscInt    nl;
5681b0f5fe93SStefano Zampini 
5682b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
5683b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
5684b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5685b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
5686b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
5687b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
5688b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5689b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
5690b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
5691b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
5692b0f5fe93SStefano Zampini     }
5693b0f5fe93SStefano Zampini   }
5694b0f5fe93SStefano Zampini 
5695b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
5696b0f5fe93SStefano Zampini     PetscBool ispreonly;
5697b0f5fe93SStefano Zampini 
5698b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
5699b0f5fe93SStefano Zampini       PetscBool isnull;
5700b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
5701b0f5fe93SStefano Zampini       if (isnull) {
570230368db7SStefano Zampini         if (isbddc && !pcbddc->benign_saddle_point) {
5703b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
5704b0f5fe93SStefano Zampini         } else {
5705b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
5706b0f5fe93SStefano Zampini         }
5707b0f5fe93SStefano Zampini       } else {
5708b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5709b0f5fe93SStefano Zampini       }
5710b0f5fe93SStefano Zampini     }
5711b0f5fe93SStefano Zampini     /* setup coarse ksp */
5712b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
5713cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
5714cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
57156e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
5716c8587f34SStefano Zampini       KSP       check_ksp;
57172b510759SStefano Zampini       KSPType   check_ksp_type;
5718c8587f34SStefano Zampini       PC        check_pc;
57196e683305SStefano Zampini       Vec       check_vec,coarse_vec;
57206a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
57212b510759SStefano Zampini       PetscInt  its;
57226e683305SStefano Zampini       PetscBool compute_eigs;
57236e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
57246e683305SStefano Zampini       PetscInt  neigs;
57258e185a42SStefano Zampini       const char *prefix;
5726c8587f34SStefano Zampini 
57272b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
57286e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
5729422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
573023ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5731f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
57322b510759SStefano Zampini       if (ispreonly) {
57332b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
57346e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
57352b510759SStefano Zampini       } else {
5736cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
57376e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
5738c8587f34SStefano Zampini       }
5739c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
57406e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
57416e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
57426e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
5743a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
5744a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
5745a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
5746a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
5747c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
5748c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
5749c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
5750c8587f34SStefano Zampini       /* create random vec */
57516e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
57526e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5753c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5754c8587f34SStefano Zampini       if (CoarseNullSpace) {
5755c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5756c8587f34SStefano Zampini       }
57576e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5758c8587f34SStefano Zampini       /* solve coarse problem */
57596e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5760c8587f34SStefano Zampini       if (CoarseNullSpace) {
57616e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5762c8587f34SStefano Zampini       }
5763cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
57646e683305SStefano Zampini       if (compute_eigs) {
5765854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5766854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
57676e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
57686e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
57696e683305SStefano Zampini         lambda_min = eigs_r[0];
57706e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
57716e683305SStefano Zampini           if (lambda_max>lambda_min) {
5772cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5773cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5774cbcc2c2aSStefano Zampini           }
5775c8587f34SStefano Zampini         }
5776c8587f34SStefano Zampini       }
5777cbcc2c2aSStefano Zampini 
5778c8587f34SStefano Zampini       /* check coarse problem residual error */
57796e683305SStefano Zampini       if (pcbddc->dbg_flag) {
57806e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
57816e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
57826e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5783c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
57846e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
57856e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5786c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5787779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
57886e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
57896e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
57906e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
57916e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5792b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
5793b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5794b0f5fe93SStefano Zampini         }
57956e683305SStefano Zampini         if (compute_eigs) {
57966e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
5797deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5798c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
57996e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
58006e683305SStefano 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);
58016e683305SStefano Zampini           for (i=0;i<neigs;i++) {
58026e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5803c8587f34SStefano Zampini           }
58046e683305SStefano Zampini         }
58056e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
58066e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
58076e683305SStefano Zampini       }
5808c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
58096e683305SStefano Zampini       if (compute_eigs) {
58106e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
58116e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5812c8587f34SStefano Zampini       }
58136e683305SStefano Zampini     }
58146e683305SStefano Zampini   }
5815cbcc2c2aSStefano Zampini   /* print additional info */
5816cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
58176e683305SStefano Zampini     /* waits until all processes reaches this point */
58186e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5819cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5820cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5821cbcc2c2aSStefano Zampini   }
5822cbcc2c2aSStefano Zampini 
58232b510759SStefano Zampini   /* free memory */
5824c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5825fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5826c8587f34SStefano Zampini   PetscFunctionReturn(0);
5827c8587f34SStefano Zampini }
5828674ae819SStefano Zampini 
5829f34684f1SStefano Zampini #undef __FUNCT__
5830f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5831f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5832f34684f1SStefano Zampini {
5833f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5834f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5835f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5836dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5837dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
583873be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5839dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5840f34684f1SStefano Zampini   PetscErrorCode ierr;
5841f34684f1SStefano Zampini 
5842f34684f1SStefano Zampini   PetscFunctionBegin;
5843f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
58440e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
58450e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5846727cdba6SStefano Zampini   }
5847dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
58483bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5849dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5850dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5851dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5852dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5853dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5854dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
58550e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
58560e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
58570e6343abSStefano Zampini   }
5858dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5859dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5860dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5861dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5862dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5863f34684f1SStefano Zampini 
5864f34684f1SStefano Zampini   /* check numbering */
5865f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5866019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5867dc456d91SStefano Zampini     PetscInt    i;
5868b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5869f34684f1SStefano Zampini 
5870f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5871f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5872f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
58731575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5874019a44ceSStefano Zampini     /* counter */
5875019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5876019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5877019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5878019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5879019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5880019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5881f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5882f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5883727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5884f34684f1SStefano Zampini     }
5885f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5886f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5887f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5888e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5889e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5890e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5891e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5892f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5893019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5894f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5895019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
589675c01103SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]);
589775c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
5898b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5899019a44ceSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a %d processes instead of %d!\n",PetscGlobalRank,i,owned,neigh);CHKERRQ(ierr);
5900f34684f1SStefano Zampini       }
5901f34684f1SStefano Zampini     }
5902019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5903b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5904f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5905f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5906f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5907f34684f1SStefano Zampini     }
5908f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5909f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5910e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5911e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5912f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5913f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5914b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5915ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5916ca8b9ea9SStefano Zampini 
5917ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
59183bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5919f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5920f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5921f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5922f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
59234bc2dc4bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d,%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i],gidxs[i]);CHKERRQ(ierr);
5924f34684f1SStefano Zampini       }
5925f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5926ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5927f34684f1SStefano Zampini     }
5928f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
59291575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5930302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5931f34684f1SStefano Zampini   }
59328bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5933f34684f1SStefano Zampini   /* get back data */
5934f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5935f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5936674ae819SStefano Zampini   PetscFunctionReturn(0);
5937674ae819SStefano Zampini }
5938674ae819SStefano Zampini 
5939e456f2a8SStefano Zampini #undef __FUNCT__
5940e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5941a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5942e456f2a8SStefano Zampini {
5943e456f2a8SStefano Zampini   IS             localis_t;
5944a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5945e456f2a8SStefano Zampini   PetscScalar    *vals;
5946e456f2a8SStefano Zampini   PetscErrorCode ierr;
5947e456f2a8SStefano Zampini 
5948e456f2a8SStefano Zampini   PetscFunctionBegin;
5949a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5950e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5951854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5952e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5953e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5954a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5955a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
59561035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5957a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
59581035eff8SStefano Zampini   }
5959a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5960e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5961e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5962a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5963a7dc3881SStefano Zampini   /* now compute set in local ordering */
5964a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5965a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5966a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5967a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5968a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5969ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5970e456f2a8SStefano Zampini       lsize++;
5971e456f2a8SStefano Zampini     }
5972e456f2a8SStefano Zampini   }
5973854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5974a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5975ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5976e456f2a8SStefano Zampini       idxs[lsize++] = i;
5977e456f2a8SStefano Zampini     }
5978e456f2a8SStefano Zampini   }
5979a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5980a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5981e456f2a8SStefano Zampini   *localis = localis_t;
5982e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5983e456f2a8SStefano Zampini }
5984906d46d4SStefano Zampini 
5985906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5986906d46d4SStefano Zampini #undef __FUNCT__
5987906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5988906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5989906d46d4SStefano Zampini {
5990906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5991906d46d4SStefano Zampini   PetscErrorCode   ierr;
5992906d46d4SStefano Zampini 
5993906d46d4SStefano Zampini   PetscFunctionBegin;
5994906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5995906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5996906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5997906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5998906d46d4SStefano Zampini   PetscFunctionReturn(0);
5999906d46d4SStefano Zampini }
6000906d46d4SStefano Zampini 
6001906d46d4SStefano Zampini #undef __FUNCT__
6002906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
6003906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
6004906d46d4SStefano Zampini {
6005906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
6006906d46d4SStefano Zampini   PetscErrorCode   ierr;
6007906d46d4SStefano Zampini 
6008906d46d4SStefano Zampini   PetscFunctionBegin;
6009906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
6010906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
6011906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
6012906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
6013906d46d4SStefano Zampini   PetscFunctionReturn(0);
6014906d46d4SStefano Zampini }
6015b96c3477SStefano Zampini 
6016b96c3477SStefano Zampini #undef __FUNCT__
6017b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
601808122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6019b96c3477SStefano Zampini {
6020a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6021b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6022b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6023a64f4aa4SStefano Zampini   Mat                 S_j;
6024b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6025b96c3477SStefano Zampini   PetscBool           free_used_adj;
6026b96c3477SStefano Zampini   PetscErrorCode      ierr;
6027b96c3477SStefano Zampini 
6028b96c3477SStefano Zampini   PetscFunctionBegin;
6029b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6030b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
603108122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6032b96c3477SStefano Zampini     used_xadj = NULL;
6033b96c3477SStefano Zampini     used_adjncy = NULL;
6034b96c3477SStefano Zampini   } else {
603508122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
603608122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
603708122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
603808122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6039b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6040b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6041b96c3477SStefano Zampini     } else {
60422fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6043b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6044b96c3477SStefano Zampini       PetscInt       nvtxs;
6045b96c3477SStefano Zampini 
60462fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
60472fffb893SStefano Zampini       if (flg_row) {
6048b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6049b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6050b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6051b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
60522fffb893SStefano Zampini       } else {
60532fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
60542fffb893SStefano Zampini         used_xadj = NULL;
60552fffb893SStefano Zampini         used_adjncy = NULL;
60562fffb893SStefano Zampini       }
60572fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6058b96c3477SStefano Zampini     }
6059b96c3477SStefano Zampini   }
6060d5574798SStefano Zampini 
6061d5574798SStefano Zampini   /* setup sub_schurs data */
6062a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6063a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
6064a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
6065a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6066ca92afb2SStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,NULL,S_j,PETSC_FALSE,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->faster_deluxe,pcbddc->adaptive_selection,PETSC_FALSE,PETSC_FALSE,0,NULL,NULL);CHKERRQ(ierr);
6067a64f4aa4SStefano Zampini   } else {
60686816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
606904708bb6SStefano Zampini     PetscBool isseqaij;
6070*a3df083aSStefano Zampini     PetscInt  benign_n;
6071*a3df083aSStefano Zampini 
60725feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
60735feab87aSStefano Zampini       PetscInt n_vertices;
60745feab87aSStefano Zampini 
60755feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
60762034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
60775feab87aSStefano Zampini     }
607804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
607904708bb6SStefano Zampini     if (!isseqaij) {
608004708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
608104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
608204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
608304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
608404708bb6SStefano Zampini       } else {
608504708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
608604708bb6SStefano Zampini       }
608704708bb6SStefano Zampini     }
6088*a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6089*a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6090ca92afb2SStefano Zampini     } else {
6091*a3df083aSStefano Zampini       benign_n = 0;
6092ca92afb2SStefano Zampini     }
6093*a3df083aSStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,pcbddc->local_mat,S_j,pcbddc->sub_schurs_exact_schur,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->faster_deluxe,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point,benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
6094ca92afb2SStefano Zampini   }
6095b96c3477SStefano Zampini 
6096b96c3477SStefano Zampini   /* free adjacency */
6097b96c3477SStefano Zampini   if (free_used_adj) {
6098b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6099b96c3477SStefano Zampini   }
6100b96c3477SStefano Zampini   PetscFunctionReturn(0);
6101b96c3477SStefano Zampini }
6102b96c3477SStefano Zampini 
6103b96c3477SStefano Zampini #undef __FUNCT__
6104b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
610508122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6106b96c3477SStefano Zampini {
6107b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6108b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6109b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6110b96c3477SStefano Zampini   PCBDDCGraph         graph;
6111b96c3477SStefano Zampini   PetscErrorCode      ierr;
6112b96c3477SStefano Zampini 
6113b96c3477SStefano Zampini   PetscFunctionBegin;
6114b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
611508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
61163301b35fSStefano Zampini     IS       verticesIS,verticescomm;
61173301b35fSStefano Zampini     PetscInt vsize,*idxs;
6118b96c3477SStefano Zampini 
6119b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
61203301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
61213301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
61223301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
61233301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
61243301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6125b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
61267fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
61273301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
61283301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6129b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6130b96c3477SStefano Zampini /*
6131b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
6132b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6133b96c3477SStefano Zampini     }
6134b96c3477SStefano Zampini */
6135b96c3477SStefano Zampini   } else {
6136b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6137b96c3477SStefano Zampini   }
6138b96c3477SStefano Zampini 
6139b96c3477SStefano Zampini   /* sub_schurs init */
6140a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6141a64f4aa4SStefano Zampini 
6142b96c3477SStefano Zampini   /* free graph struct */
614308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6144b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6145b96c3477SStefano Zampini   }
6146b96c3477SStefano Zampini   PetscFunctionReturn(0);
6147b96c3477SStefano Zampini }
6148fa34dd3eSStefano Zampini 
6149fa34dd3eSStefano Zampini #undef __FUNCT__
6150fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6151fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6152fa34dd3eSStefano Zampini {
6153fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6154fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6155fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6156fa34dd3eSStefano Zampini 
6157fa34dd3eSStefano Zampini   PetscFunctionBegin;
6158fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6159fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
61604f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6161fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
61624f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
616375c01103SStefano Zampini     PetscReal      norm;
6164fa34dd3eSStefano Zampini     PetscInt       i;
6165fa34dd3eSStefano Zampini 
6166fa34dd3eSStefano Zampini     /* B0 and B0_B */
6167fa34dd3eSStefano Zampini     if (zerodiag) {
6168fa34dd3eSStefano Zampini       IS       dummy;
6169fa34dd3eSStefano Zampini 
61704f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
61714f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6172fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6173fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6174fa34dd3eSStefano Zampini     }
6175fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6176fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6177fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6178fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6179fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6180fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6181fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6182fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6183fa34dd3eSStefano Zampini     /* S_j */
6184fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6185fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6186fa34dd3eSStefano Zampini 
6187fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6188fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6189fa34dd3eSStefano Zampini     /* continuous in primal space */
6190fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6191fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6192fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6193fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
61944f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
61954f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6196fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6197fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6198fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6199fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6200fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6201fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6202fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6203fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6204fa34dd3eSStefano Zampini 
6205fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6206fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6207fa34dd3eSStefano Zampini     /* local with Schur */
6208fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6209fa34dd3eSStefano Zampini     if (zerodiag) {
6210fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
62114f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6212fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6213fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6214fa34dd3eSStefano Zampini     }
6215fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6216fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6217fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6218fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6219fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6220fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6221fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6222fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6223fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6224fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6225fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6226fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6227fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6228fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6229fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6230fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6231fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6232fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6233fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6234fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6235fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6236fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6237fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6238fa34dd3eSStefano Zampini     if (zerodiag) {
6239fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6240fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
62414f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6242fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6243fa34dd3eSStefano Zampini     }
6244fa34dd3eSStefano Zampini     /* BDDC */
6245fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6246fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6247fa34dd3eSStefano Zampini 
6248fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6249fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6250fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6251fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
62524f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
62534f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6254fa34dd3eSStefano Zampini     }
62554f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6256fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6257fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6258fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6259fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6260fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6261fa34dd3eSStefano Zampini   }
6262fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6263fa34dd3eSStefano Zampini }
6264