xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision d4d8cf7b04c8af6b42c348aee4a8cc8798655e9e)
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 
9a3df083aSStefano Zampini #undef __FUNCT__
10a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
11a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
12a3df083aSStefano Zampini {
13a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
14a3df083aSStefano Zampini   PetscErrorCode          ierr;
15a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
16a3df083aSStefano Zampini 
17a3df083aSStefano Zampini   PetscFunctionBegin;
18a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
19a3df083aSStefano Zampini   if (transpose) {
20a3df083aSStefano Zampini     apply_right = ctx->apply_left;
21a3df083aSStefano Zampini     apply_left = ctx->apply_right;
22a3df083aSStefano Zampini   } else {
23a3df083aSStefano Zampini     apply_right = ctx->apply_right;
24a3df083aSStefano Zampini     apply_left = ctx->apply_left;
25a3df083aSStefano Zampini   }
26a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
27a3df083aSStefano Zampini   if (apply_right) {
28a3df083aSStefano Zampini     const PetscScalar *ax;
29a3df083aSStefano Zampini     PetscInt          nl,i;
30a3df083aSStefano Zampini 
31a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
32a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
33a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
34a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
35a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
36a3df083aSStefano Zampini       PetscScalar    sum,val;
37a3df083aSStefano Zampini       const PetscInt *idxs;
38a3df083aSStefano Zampini       PetscInt       nz,j;
39a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
40a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
41a3df083aSStefano Zampini       sum = 0.;
42a3df083aSStefano Zampini       if (ctx->apply_p0) {
43a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
44a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
45a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
46a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
47a3df083aSStefano Zampini         }
48a3df083aSStefano Zampini       } else {
49a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
50a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
51a3df083aSStefano Zampini         }
52a3df083aSStefano Zampini       }
53a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
54a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
55a3df083aSStefano Zampini     }
56a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
57a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
58a3df083aSStefano Zampini   }
59a3df083aSStefano Zampini   if (transpose) {
60a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
61a3df083aSStefano Zampini   } else {
62a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
63a3df083aSStefano Zampini   }
64a3df083aSStefano Zampini   if (reset_x) {
65a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
66a3df083aSStefano Zampini   }
67a3df083aSStefano Zampini   if (apply_left) {
68a3df083aSStefano Zampini     PetscScalar *ay;
69a3df083aSStefano Zampini     PetscInt    i;
70a3df083aSStefano Zampini 
71a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
72a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
73a3df083aSStefano Zampini       PetscScalar    sum,val;
74a3df083aSStefano Zampini       const PetscInt *idxs;
75a3df083aSStefano Zampini       PetscInt       nz,j;
76a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
77a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
78a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
79a3df083aSStefano Zampini       if (ctx->apply_p0) {
80a3df083aSStefano Zampini         sum = 0.;
81a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
82a3df083aSStefano Zampini           sum += ay[idxs[j]];
83a3df083aSStefano Zampini           ay[idxs[j]] += val;
84a3df083aSStefano Zampini         }
85a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
86a3df083aSStefano Zampini       } else {
87a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
88a3df083aSStefano Zampini           ay[idxs[j]] += val;
89a3df083aSStefano Zampini         }
90a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
91a3df083aSStefano Zampini       }
92a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
93a3df083aSStefano Zampini     }
94a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
95a3df083aSStefano Zampini   }
96a3df083aSStefano Zampini   PetscFunctionReturn(0);
97a3df083aSStefano Zampini }
98a3df083aSStefano Zampini 
99a3df083aSStefano Zampini #undef __FUNCT__
100a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
101a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
102a3df083aSStefano Zampini {
103a3df083aSStefano Zampini   PetscErrorCode ierr;
104a3df083aSStefano Zampini 
105a3df083aSStefano Zampini   PetscFunctionBegin;
106a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
107a3df083aSStefano Zampini   PetscFunctionReturn(0);
108a3df083aSStefano Zampini }
109a3df083aSStefano Zampini 
110a3df083aSStefano Zampini #undef __FUNCT__
111a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
112a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
113a3df083aSStefano Zampini {
114a3df083aSStefano Zampini   PetscErrorCode ierr;
115a3df083aSStefano Zampini 
116a3df083aSStefano Zampini   PetscFunctionBegin;
117a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
118a3df083aSStefano Zampini   PetscFunctionReturn(0);
119a3df083aSStefano Zampini }
120a3df083aSStefano Zampini 
121a3df083aSStefano Zampini #undef __FUNCT__
122a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
123a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
124a3df083aSStefano Zampini {
125a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
126a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
127a3df083aSStefano Zampini   Mat_IS                  *matis = (Mat_IS*)pc->pmat->data;
128a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
129a3df083aSStefano Zampini   PetscErrorCode          ierr;
130a3df083aSStefano Zampini 
131a3df083aSStefano Zampini   PetscFunctionBegin;
132a3df083aSStefano Zampini   if (!restore) {
133a3df083aSStefano Zampini     Mat                A,A_IB,A_BI;
134a3df083aSStefano Zampini     PetscScalar        *work;
135df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs->reuse_solver;
136a3df083aSStefano Zampini 
137a3df083aSStefano Zampini     if (!reuse) {
138a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot setup shell matrices!");
139a3df083aSStefano Zampini     }
140a3df083aSStefano Zampini 
141a3df083aSStefano Zampini     /* local mat */
142a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A);CHKERRQ(ierr);
143a3df083aSStefano Zampini     ierr = MatSetSizes(A,pcis->n,pcis->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
144a3df083aSStefano Zampini     ierr = MatSetType(A,MATSHELL);CHKERRQ(ierr);
145a3df083aSStefano Zampini     ierr = MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
146a3df083aSStefano Zampini     ierr = MatShellSetOperation(A,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
147a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
148a3df083aSStefano Zampini     ierr = MatShellSetContext(A,ctx);CHKERRQ(ierr);
149a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
150a3df083aSStefano Zampini     ctx->apply_right = PETSC_TRUE;
151a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_TRUE;
152a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
153a3df083aSStefano Zampini     ctx->benign_zerodiag_subs = pcbddc->benign_zerodiag_subs;
154a3df083aSStefano Zampini     ctx->A = matis->A;
155a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
156a3df083aSStefano Zampini     ctx->work = work;
157a3df083aSStefano Zampini     ierr = MatSetUp(A);CHKERRQ(ierr);
158a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
159a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
160a3df083aSStefano Zampini     matis->A = A;
161a3df083aSStefano Zampini 
162a3df083aSStefano Zampini     /* A_IB */
163a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
164a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
165a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
166a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
167a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
168a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
169a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
170a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
171a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
172a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
173a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
174a3df083aSStefano Zampini     ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
175a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
176a3df083aSStefano Zampini     ctx->work = work;
177a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
178a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180a3df083aSStefano Zampini     pcis->A_IB = A_IB;
181a3df083aSStefano Zampini 
182a3df083aSStefano Zampini     /* A_BI as A_IB^T */
183a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
184a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
185a3df083aSStefano Zampini     pcis->A_BI = A_BI;
186a3df083aSStefano Zampini   } else {
187a3df083aSStefano Zampini     ierr = MatShellGetContext(matis->A,&ctx);CHKERRQ(ierr);
188a3df083aSStefano Zampini     ierr = MatDestroy(&matis->A);CHKERRQ(ierr);
189a3df083aSStefano Zampini     matis->A = ctx->A;
190a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
191a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
192a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
193a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
194a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
195a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
196a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
197a3df083aSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
198a3df083aSStefano Zampini     pcbddc->benign_original_mat = NULL;
199a3df083aSStefano Zampini   }
200a3df083aSStefano Zampini   PetscFunctionReturn(0);
201a3df083aSStefano Zampini }
202a3df083aSStefano Zampini 
203a3df083aSStefano Zampini /* used just in bddc debug mode */
204a3df083aSStefano Zampini #undef __FUNCT__
205a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
206a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
207a3df083aSStefano Zampini {
208a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
209a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
210a3df083aSStefano Zampini   Mat            An;
211a3df083aSStefano Zampini   PetscErrorCode ierr;
212a3df083aSStefano Zampini 
213a3df083aSStefano Zampini   PetscFunctionBegin;
214a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
215a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
216a3df083aSStefano Zampini   if (is1) {
217a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
218a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
219a3df083aSStefano Zampini   } else {
220a3df083aSStefano Zampini     *B = An;
221a3df083aSStefano Zampini   }
222a3df083aSStefano Zampini   PetscFunctionReturn(0);
223a3df083aSStefano Zampini }
224a3df083aSStefano 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;
402d12d3064SStefano Zampini     PetscInt       nz,*count;
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);
443d12d3064SStefano Zampini 
444d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
445d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
446d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
447d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
448d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
449d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
450*d4d8cf7bSStefano Zampini     for (i=0;i<nz;i++) {
451d12d3064SStefano Zampini       if (count[idxs[i]]) {
452d12d3064SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
453d12d3064SStefano Zampini       }
454*d4d8cf7bSStefano Zampini     }
455d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
456d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
4575408967cSStefano Zampini   }
458dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
4595408967cSStefano Zampini 
4605408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
4615408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
4624f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
4635408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
4644f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
4655408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
4664f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
4674f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
4684f1b2e48SStefano 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);
4694f1b2e48SStefano Zampini     }
4705408967cSStefano Zampini   }
4715408967cSStefano Zampini   PetscFunctionReturn(0);
4725408967cSStefano Zampini }
4735408967cSStefano Zampini 
4745408967cSStefano Zampini #undef __FUNCT__
475339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
476339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
477339f8db1SStefano Zampini {
478339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4794f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
480b0f5fe93SStefano Zampini   PetscInt       nz,n;
4814f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
482339f8db1SStefano Zampini   PetscErrorCode ierr;
483339f8db1SStefano Zampini 
484339f8db1SStefano Zampini   PetscFunctionBegin;
4859f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
4869f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
487339f8db1SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
488a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
489a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
490a3df083aSStefano Zampini   }
491a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
492a3df083aSStefano Zampini   pcbddc->benign_n = 0;
4934f1b2e48SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
4944f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
4954f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
4964f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
4974f1b2e48SStefano Zampini      since the local Schur complements are SPD
4984f1b2e48SStefano Zampini   */
4994f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
5004f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
50140fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
5024f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
5034f1b2e48SStefano Zampini 
5044f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
5054f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
5064f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
5074f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
508ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
50940fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
51040fa8d13SStefano Zampini     if (!sorted) {
51140fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
51240fa8d13SStefano Zampini     }
51340fa8d13SStefano Zampini   } else {
51440fa8d13SStefano Zampini     pressures = NULL;
51540fa8d13SStefano Zampini   }
51697d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
51797d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
51897d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
519339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
520339f8db1SStefano Zampini   if (!sorted) {
521339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
522339f8db1SStefano Zampini   }
523339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5244f1b2e48SStefano Zampini   if (!nz) {
5254f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
5264f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
52740fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
52840fa8d13SStefano Zampini   }
5294f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
5304f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
5314f1b2e48SStefano Zampini   zerodiag_subs = NULL;
5324f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
5334f1b2e48SStefano Zampini   if (has_null_pressures) {
5344f1b2e48SStefano Zampini     IS       *subs;
5354f1b2e48SStefano Zampini     PetscInt nsubs,i;
5364f1b2e48SStefano Zampini 
5374f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
5384f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
5394f1b2e48SStefano Zampini     if (nsubs > 1) {
5404f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
5414f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
5424f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
5434f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
5444f1b2e48SStefano Zampini         PetscInt               nl;
5454f1b2e48SStefano Zampini 
5464f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
5474f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
5484f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
5494f1b2e48SStefano Zampini         if (nl) {
5504f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
5514f1b2e48SStefano Zampini 
5524f1b2e48SStefano Zampini           if (pressures) {
5534f1b2e48SStefano Zampini             IS t_pressure_subs;
5544f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
5554f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
5564f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
5574f1b2e48SStefano Zampini           }
5584f1b2e48SStefano Zampini           if (valid) {
5594f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
5604f1b2e48SStefano Zampini             pcbddc->benign_n++;
5614f1b2e48SStefano Zampini           } else {
5624f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
5634f1b2e48SStefano Zampini           }
5644f1b2e48SStefano Zampini         }
5654f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
5664f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
5674f1b2e48SStefano Zampini       }
5684f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
5694f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
5704f1b2e48SStefano Zampini       if (pressures) {
5714f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
5724f1b2e48SStefano Zampini       }
5734f1b2e48SStefano Zampini       if (valid) {
5744f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
575ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
5764f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
5774f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
5784f1b2e48SStefano Zampini       }
5794f1b2e48SStefano Zampini     }
5804f1b2e48SStefano Zampini   }
5814f1b2e48SStefano Zampini 
5824f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
5834f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
5844f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
5854f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
5864f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
5874f1b2e48SStefano Zampini   }
5884f1b2e48SStefano Zampini 
5894f1b2e48SStefano Zampini   /* final check for null pressures */
5904f1b2e48SStefano Zampini   if (zerodiag && pressures) {
5914f1b2e48SStefano Zampini     PetscInt nz,np;
5924f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5934f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
5944f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
5954f1b2e48SStefano Zampini   }
5964f1b2e48SStefano Zampini 
5974f1b2e48SStefano Zampini   if (recompute_zerodiag) {
5984f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
5994f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
6004f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
6014f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
6024f1b2e48SStefano Zampini     } else {
6034f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
6044f1b2e48SStefano Zampini 
6054f1b2e48SStefano Zampini       nzn = 0;
6064f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
6074f1b2e48SStefano Zampini         PetscInt ns;
6084f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
6094f1b2e48SStefano Zampini         nzn += ns;
6104f1b2e48SStefano Zampini       }
6114f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
6124f1b2e48SStefano Zampini       nzn = 0;
6134f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
6144f1b2e48SStefano Zampini         PetscInt ns,*idxs;
6154f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
6164f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
6174f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
6184f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
6194f1b2e48SStefano Zampini         nzn += ns;
6204f1b2e48SStefano Zampini       }
6214f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
6224f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
6234f1b2e48SStefano Zampini     }
6244f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
6254f1b2e48SStefano Zampini   }
6264f1b2e48SStefano Zampini 
6274f1b2e48SStefano Zampini   if (has_null_pressures) {
6284f1b2e48SStefano Zampini     IS             zerodiagc;
6294f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
6304f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
6314f1b2e48SStefano Zampini 
6324f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
633339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
634339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
635339f8db1SStefano Zampini     /* local change of basis for pressures */
636339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
63797d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
638339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
639339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
640339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
6414f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
6424f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
6434f1b2e48SStefano Zampini       PetscInt nzs,j;
6444f1b2e48SStefano Zampini 
6454f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
6464f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
6474f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
6484f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
6494f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
6504f1b2e48SStefano Zampini     }
651339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
652339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
653339f8db1SStefano Zampini     /* set identity on velocities */
654339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
655339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
656339f8db1SStefano Zampini     }
6574f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
6584f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
6599f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
6604f1b2e48SStefano 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);
661339f8db1SStefano Zampini     /* set change on pressures */
6624f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
6634f1b2e48SStefano Zampini       PetscScalar *array;
6644f1b2e48SStefano Zampini       PetscInt    nzs;
6654f1b2e48SStefano Zampini 
6664f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
6674f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
6684f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
669339f8db1SStefano Zampini         PetscScalar vals[2];
670339f8db1SStefano Zampini         PetscInt    cols[2];
671339f8db1SStefano Zampini 
672339f8db1SStefano Zampini         cols[0] = idxs[i];
6734f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
674339f8db1SStefano Zampini         vals[0] = 1.;
675b0f5fe93SStefano Zampini         vals[1] = 1.;
6764f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
677339f8db1SStefano Zampini       }
6784f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
6794f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
6804f1b2e48SStefano Zampini       array[nzs-1] = 1.;
6814f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
6824f1b2e48SStefano Zampini       /* store local idxs for p0 */
6834f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
6844f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
685339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
6864f1b2e48SStefano Zampini     }
687339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
688339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
689a3df083aSStefano Zampini     /* project if needed */
690a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
69197d764eeSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&pcbddc->benign_original_mat);CHKERRQ(ierr);
692339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
69397d764eeSStefano Zampini       ierr = MatSeqAIJCompress(pcbddc->benign_original_mat,&pcbddc->local_mat);CHKERRQ(ierr);
69497d764eeSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
695a3df083aSStefano Zampini     }
6964f1b2e48SStefano Zampini     /* store global idxs for p0 */
6974f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
698339f8db1SStefano Zampini   }
699ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
7004f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
701b0f5fe93SStefano Zampini 
702b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
703b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
704339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
705339f8db1SStefano Zampini   PetscFunctionReturn(0);
706339f8db1SStefano Zampini }
707339f8db1SStefano Zampini 
708339f8db1SStefano Zampini #undef __FUNCT__
709015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
710015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
711efc2fbd9SStefano Zampini {
712efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
713efc2fbd9SStefano Zampini   PetscErrorCode ierr;
714efc2fbd9SStefano Zampini 
715efc2fbd9SStefano Zampini   PetscFunctionBegin;
716efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
717efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
7184f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
719efc2fbd9SStefano Zampini   }
720015636ebSStefano Zampini   if (get) { /* use SF to get values */
721efc2fbd9SStefano Zampini     PetscScalar *array;
722efc2fbd9SStefano Zampini 
723efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
7244f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
7254f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
726efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
7274f1b2e48SStefano Zampini   } else { /* use VecSetValues (not scalable, I should try to find a better solution (defining a new MPI_OP for reduction) */
7284f1b2e48SStefano Zampini     ierr = VecSetValues(v,pcbddc->benign_n,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
729efc2fbd9SStefano Zampini     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
730efc2fbd9SStefano Zampini     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
731efc2fbd9SStefano Zampini   }
732efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
733efc2fbd9SStefano Zampini }
734efc2fbd9SStefano Zampini 
735efc2fbd9SStefano Zampini #undef __FUNCT__
736c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
737c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
738c263805aSStefano Zampini {
739c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
740c263805aSStefano Zampini   PetscErrorCode ierr;
741c263805aSStefano Zampini 
742c263805aSStefano Zampini   PetscFunctionBegin;
743c263805aSStefano Zampini   /* TODO: add error checking
744c263805aSStefano Zampini     - avoid nested pop (or push) calls.
745c263805aSStefano Zampini     - cannot push before pop.
7461c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
747c263805aSStefano Zampini   */
7484f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
749efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
750efc2fbd9SStefano Zampini   }
751c263805aSStefano Zampini   if (pop) {
752a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
7534f1b2e48SStefano Zampini       IS       is_p0;
7544f1b2e48SStefano Zampini       MatReuse reuse;
755c263805aSStefano Zampini 
756c263805aSStefano Zampini       /* extract B_0 */
7574f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
7584f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
7594f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
7604f1b2e48SStefano Zampini       }
7614f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
7624f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
763c263805aSStefano Zampini       /* remove rows and cols from local problem */
764c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
76597d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7664f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
7674f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
768a3df083aSStefano Zampini     } else {
769a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
770a3df083aSStefano Zampini       PetscScalar *vals;
771a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
772a3df083aSStefano Zampini 
773a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
774a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
775a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
776a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
777a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
778a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
779a3df083aSStefano Zampini         /* this matrix is very sparse: the nnz pattern is not known unless we do 2 sweeps of the next loop.
780a3df083aSStefano Zampini            Setting nnz=100 should be more than enough */
781a3df083aSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,100,NULL);CHKERRQ(ierr);
782a3df083aSStefano Zampini       }
783a3df083aSStefano Zampini 
784a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
785a3df083aSStefano Zampini         PetscScalar *array;
786a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
787a3df083aSStefano Zampini 
788a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
789a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
790a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
791a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
792a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
793a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
794a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
795a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
796a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
797a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
798a3df083aSStefano Zampini         cum = 0;
799a3df083aSStefano Zampini         for (j=0;j<n;j++) {
800a3df083aSStefano Zampini           if (PetscUnlikely(PetscAbsReal(array[j]) > PETSC_SMALL)) {
801a3df083aSStefano Zampini             vals[cum] = array[j];
802a3df083aSStefano Zampini             idxs_ins[cum] = j;
803a3df083aSStefano Zampini             cum++;
804a3df083aSStefano Zampini           }
805a3df083aSStefano Zampini         }
806a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
807a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
808a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
809a3df083aSStefano Zampini       }
810a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
811a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
812a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
813a3df083aSStefano Zampini     }
814c263805aSStefano Zampini   } else { /* push */
815a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
8164f1b2e48SStefano Zampini       PetscInt i;
8174f1b2e48SStefano Zampini 
8184f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
8194f1b2e48SStefano Zampini         PetscScalar *B0_vals;
8204f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
8214f1b2e48SStefano Zampini 
8224f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
8234f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
8247b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
8254f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
8264f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
8274f1b2e48SStefano Zampini       }
828c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
829c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
830a3df083aSStefano Zampini     } else {
831a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
832a3df083aSStefano Zampini     }
833c263805aSStefano Zampini   }
834c263805aSStefano Zampini   PetscFunctionReturn(0);
835c263805aSStefano Zampini }
836c263805aSStefano Zampini 
837c263805aSStefano Zampini #undef __FUNCT__
838b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
83908122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
840b1b3d7a2SStefano Zampini {
841b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
84208122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
84308122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
84408122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
84508122e43SStefano Zampini   PetscScalar     *work,lwork;
84608122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
84708122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
84808122e43SStefano Zampini   PetscReal       *eigs,thresh;
8491b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
850f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
85108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
85208122e43SStefano Zampini   PetscReal       *rwork;
85308122e43SStefano Zampini #endif
854b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
855b1b3d7a2SStefano Zampini 
856b1b3d7a2SStefano Zampini   PetscFunctionBegin;
857df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
858df4d28bfSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
85908122e43SStefano Zampini   }
86008122e43SStefano Zampini 
86106a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
86206a4e24aSStefano 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);
86306a4e24aSStefano Zampini   }
86406a4e24aSStefano Zampini 
865fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
866fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
867fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
868fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
8691575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
870fd14bc51SStefano Zampini   }
871fd14bc51SStefano Zampini 
872e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
873e496cd5dSStefano 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);
874e496cd5dSStefano Zampini   }
875e496cd5dSStefano Zampini 
87608122e43SStefano Zampini   /* max size of subsets */
87708122e43SStefano Zampini   mss = 0;
87808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
87908122e43SStefano Zampini     PetscInt subset_size;
880862806e4SStefano Zampini 
88108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
88208122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
88308122e43SStefano Zampini   }
88408122e43SStefano Zampini 
88508122e43SStefano Zampini   /* min/max and threshold */
88608122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
887f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
88808122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
889f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
890f6f667cfSStefano Zampini   if (nmin) {
891f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
892f6f667cfSStefano Zampini   }
89308122e43SStefano Zampini 
89408122e43SStefano Zampini   /* allocate lapack workspace */
89508122e43SStefano Zampini   cum = cum2 = 0;
89608122e43SStefano Zampini   maxneigs = 0;
89708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
89808122e43SStefano Zampini     PetscInt n,subset_size;
899f6f667cfSStefano Zampini 
90008122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
90108122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
9029162d606SStefano Zampini     cum += subset_size;
9039162d606SStefano Zampini     cum2 += subset_size*n;
90408122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
90508122e43SStefano Zampini   }
90608122e43SStefano Zampini   if (mss) {
9079ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
90808122e43SStefano Zampini       PetscBLASInt B_itype = 1;
90908122e43SStefano Zampini       PetscBLASInt B_N = mss;
9104c6709b3SStefano Zampini       PetscReal    zero = 0.0;
9114c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
91208122e43SStefano Zampini 
91308122e43SStefano Zampini       B_lwork = -1;
91408122e43SStefano Zampini       S = NULL;
91508122e43SStefano Zampini       St = NULL;
916a58a30b4SStefano Zampini       eigs = NULL;
917a58a30b4SStefano Zampini       eigv = NULL;
918a58a30b4SStefano Zampini       B_iwork = NULL;
919a58a30b4SStefano Zampini       B_ifail = NULL;
920d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
921d1710679SStefano Zampini       rwork = NULL;
922d1710679SStefano Zampini #endif
9238bec7fa6SStefano Zampini       thresh = 1.0;
92408122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
92508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
92608122e43SStefano 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));
92708122e43SStefano Zampini #else
92808122e43SStefano 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));
92908122e43SStefano Zampini #endif
93008122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
93108122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
93208122e43SStefano Zampini     } else {
93308122e43SStefano Zampini         /* TODO */
93408122e43SStefano Zampini     }
93508122e43SStefano Zampini   } else {
93608122e43SStefano Zampini     lwork = 0;
93708122e43SStefano Zampini   }
93808122e43SStefano Zampini 
93908122e43SStefano Zampini   nv = 0;
940d62866d3SStefano 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) */
941d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
94208122e43SStefano Zampini   }
9434c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
944f6f667cfSStefano Zampini   if (allocated_S_St) {
945f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
946f6f667cfSStefano Zampini   }
947f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
94808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
94908122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
95008122e43SStefano Zampini #endif
9519162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
9529162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
9539162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
95408122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
9559162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
95608122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
95708122e43SStefano Zampini 
95808122e43SStefano Zampini   maxneigs = 0;
95908122e43SStefano Zampini   cum = cum2 = cumarray = 0;
9609162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
9619162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
962d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
96308122e43SStefano Zampini     const PetscInt *idxs;
96408122e43SStefano Zampini 
965d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
96608122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
96708122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
96808122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
96908122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
9709162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
9719162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
97208122e43SStefano Zampini     }
97308122e43SStefano Zampini     cum2 = cum;
974d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
97508122e43SStefano Zampini   }
97608122e43SStefano Zampini 
97708122e43SStefano Zampini   if (mss) { /* multilevel */
97808122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
97908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
98008122e43SStefano Zampini   }
98108122e43SStefano Zampini 
982ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
98308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
98408122e43SStefano Zampini     const PetscInt *idxs;
985f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
986862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
98708122e43SStefano Zampini     PetscBLASInt   B_N;
988aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
98908122e43SStefano Zampini 
990862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
991ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
992f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
993f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
9949ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
995aff50787SStefano Zampini         PetscInt j,k;
996aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
997aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
998aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
99908122e43SStefano Zampini         }
100008122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1001aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1002aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1003aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1004aff50787SStefano Zampini           }
100508122e43SStefano Zampini         }
100608122e43SStefano Zampini       } else {
100708122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
100808122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
100908122e43SStefano Zampini       }
10108bec7fa6SStefano Zampini     } else {
1011f6f667cfSStefano Zampini       S = Sarray + cumarray;
1012f6f667cfSStefano Zampini       St = Starray + cumarray;
10138bec7fa6SStefano Zampini     }
101408122e43SStefano Zampini 
1015aff50787SStefano Zampini     /* see if we can save some work */
1016aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
1017aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1018aff50787SStefano Zampini     }
1019aff50787SStefano Zampini 
1020aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
1021aff50787SStefano Zampini       B_neigs = 0;
1022aff50787SStefano Zampini     } else {
10239ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
102408122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1025f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
10264c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
10279552c7c7SStefano Zampini         PetscInt     nmin_s;
102808122e43SStefano Zampini 
1029fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
10308bec7fa6SStefano 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]]);
1031fd14bc51SStefano Zampini         }
1032d16cbb6bSStefano Zampini 
103308122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1034d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
1035d16cbb6bSStefano Zampini 
1036d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
103708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1038f6f667cfSStefano 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));
103908122e43SStefano Zampini #else
1040f6f667cfSStefano 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));
104108122e43SStefano Zampini #endif
1042d16cbb6bSStefano Zampini         } else {
1043d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1044d16cbb6bSStefano Zampini           B_IL = 1;
1045d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1046d16cbb6bSStefano 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));
1047d16cbb6bSStefano Zampini #else
1048d16cbb6bSStefano 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));
1049d16cbb6bSStefano Zampini #endif
1050d16cbb6bSStefano Zampini         }
105108122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
105208122e43SStefano Zampini         if (B_ierr) {
105308122e43SStefano Zampini           if (B_ierr < 0 ) {
105408122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
105508122e43SStefano Zampini           } else if (B_ierr <= B_N) {
105608122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
105708122e43SStefano Zampini           } else {
10589552c7c7SStefano 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);
105908122e43SStefano Zampini           }
106008122e43SStefano Zampini         }
106108122e43SStefano Zampini 
106208122e43SStefano Zampini         if (B_neigs > nmax) {
1063fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1064fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1065fd14bc51SStefano Zampini           }
1066f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
106708122e43SStefano Zampini           B_neigs = nmax;
106808122e43SStefano Zampini         }
106908122e43SStefano Zampini 
10709552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
10719552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
107208122e43SStefano Zampini           PetscBLASInt B_neigs2;
107308122e43SStefano Zampini 
1074f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
1075f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
1076fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1077fd14bc51SStefano 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);
1078fd14bc51SStefano Zampini           }
10799ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
108008122e43SStefano Zampini             PetscInt j;
108108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
108208122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
108308122e43SStefano Zampini             }
108408122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
108508122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
108608122e43SStefano Zampini             }
108708122e43SStefano Zampini           } else {
108808122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
108908122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
109008122e43SStefano Zampini           }
109108122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
109208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1093f6f667cfSStefano 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));
109408122e43SStefano Zampini #else
1095f6f667cfSStefano 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));
109608122e43SStefano Zampini #endif
109708122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
109808122e43SStefano Zampini           B_neigs += B_neigs2;
109908122e43SStefano Zampini         }
110008122e43SStefano Zampini         if (B_ierr) {
110108122e43SStefano Zampini           if (B_ierr < 0 ) {
110208122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
110308122e43SStefano Zampini           } else if (B_ierr <= B_N) {
110408122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
110508122e43SStefano Zampini           } else {
11069552c7c7SStefano 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);
110708122e43SStefano Zampini           }
110808122e43SStefano Zampini         }
1109fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1110ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
111108122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
111208122e43SStefano Zampini             if (eigs[j] == 0.0) {
1113ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
111408122e43SStefano Zampini             } else {
1115ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
1116fd14bc51SStefano Zampini             }
111708122e43SStefano Zampini           }
111808122e43SStefano Zampini         }
111908122e43SStefano Zampini       } else {
112008122e43SStefano Zampini           /* TODO */
112108122e43SStefano Zampini       }
1122aff50787SStefano Zampini     }
11238bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
11248bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
11259162d606SStefano Zampini     if (B_neigs) {
11269162d606SStefano 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);
1127fd14bc51SStefano Zampini 
1128fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
11299552c7c7SStefano Zampini         PetscInt ii;
11309552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1131ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
11329552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1133ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1134ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1135ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1136ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1137ac47001eSStefano Zampini #else
1138ac47001eSStefano 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);
1139ac47001eSStefano Zampini #endif
11409552c7c7SStefano Zampini           }
11419552c7c7SStefano Zampini         }
1142fd14bc51SStefano Zampini       }
114308122e43SStefano Zampini #if 0
11449162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
114508122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
114608122e43SStefano Zampini         PetscScalar norm;
114708122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
11489162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
11499162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
115008122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
115108122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
115208122e43SStefano Zampini         } else {
115308122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
115408122e43SStefano Zampini         }
11559162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
1156b1b3d7a2SStefano Zampini       }
1157b1b3d7a2SStefano Zampini #endif
11589162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
11599162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
11609162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
11619162d606SStefano Zampini       cum++;
116208122e43SStefano Zampini     }
116308122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
116408122e43SStefano Zampini     /* shift for next computation */
116508122e43SStefano Zampini     cumarray += subset_size*subset_size;
116608122e43SStefano Zampini   }
1167fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1168fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1169fd14bc51SStefano Zampini   }
117008122e43SStefano Zampini 
117108122e43SStefano Zampini   if (mss) {
117208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
117308122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1174f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1175f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1176f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
117708122e43SStefano Zampini   }
1178f6f667cfSStefano Zampini   if (allocated_S_St) {
1179f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1180f6f667cfSStefano Zampini   }
1181f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
118208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
118308122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
118408122e43SStefano Zampini #endif
118508122e43SStefano Zampini   if (pcbddc->dbg_flag) {
11861b968477SStefano Zampini     PetscInt maxneigs_r;
118708122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
11889b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
118908122e43SStefano Zampini   }
119008122e43SStefano Zampini   PetscFunctionReturn(0);
119108122e43SStefano Zampini }
1192b1b3d7a2SStefano Zampini 
1193674ae819SStefano Zampini #undef __FUNCT__
1194c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1195c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1196c8587f34SStefano Zampini {
1197c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
11988629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1199c8587f34SStefano Zampini   PetscErrorCode ierr;
1200c8587f34SStefano Zampini 
1201c8587f34SStefano Zampini   PetscFunctionBegin;
1202f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
12035e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1204c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1205c8587f34SStefano Zampini 
1206684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
12070fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1208684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1209c8587f34SStefano Zampini 
1210c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1211b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
1212c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1213c8587f34SStefano Zampini   }
1214c8587f34SStefano Zampini 
12158629588bSStefano Zampini   /*
12168629588bSStefano Zampini      Setup local correction and local part of coarse basis.
12178629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
12188629588bSStefano Zampini   */
121947f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
12208629588bSStefano Zampini 
12218629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
12228629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
12238629588bSStefano Zampini 
12248629588bSStefano Zampini   /* free */
12258629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1226c8587f34SStefano Zampini   PetscFunctionReturn(0);
1227c8587f34SStefano Zampini }
1228c8587f34SStefano Zampini 
1229c8587f34SStefano Zampini #undef __FUNCT__
1230674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1231674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1232674ae819SStefano Zampini {
1233674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1234674ae819SStefano Zampini   PetscErrorCode ierr;
1235674ae819SStefano Zampini 
1236674ae819SStefano Zampini   PetscFunctionBegin;
1237674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1238674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
123930368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1240674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
1241674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1242785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1243674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1244f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1245f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1246785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
124763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
124863602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1249674ae819SStefano Zampini   PetscFunctionReturn(0);
1250674ae819SStefano Zampini }
1251674ae819SStefano Zampini 
1252674ae819SStefano Zampini #undef __FUNCT__
1253674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1254674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1255674ae819SStefano Zampini {
1256674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12574f1b2e48SStefano Zampini   PetscInt       i;
1258674ae819SStefano Zampini   PetscErrorCode ierr;
1259674ae819SStefano Zampini 
1260674ae819SStefano Zampini   PetscFunctionBegin;
1261b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1262674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
1263674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1264674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
12654f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
12664f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
12674f1b2e48SStefano Zampini   }
12684f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1269b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1270674ae819SStefano Zampini   PetscFunctionReturn(0);
1271674ae819SStefano Zampini }
1272674ae819SStefano Zampini 
1273674ae819SStefano Zampini #undef __FUNCT__
1274674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1275674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1276674ae819SStefano Zampini {
1277674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1278674ae819SStefano Zampini   PetscErrorCode ierr;
1279674ae819SStefano Zampini 
1280674ae819SStefano Zampini   PetscFunctionBegin;
1281674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
128258da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1283ca92afb2SStefano Zampini     PetscScalar *array;
128406656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
128506656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
128658da7f69SStefano Zampini   }
1287674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1288674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
128915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
129015aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1291674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1292674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1293674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
129406656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1295674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1296674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
12978ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1298674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1299674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1300674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1301f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1302f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1303f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1304f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1305727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
13060e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1307f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
130870cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
13096e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
131081d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
13110369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
13128b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
13134f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
13148b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1315ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1316ca92afb2SStefano Zampini     PetscInt i;
1317ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1318ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1319ca92afb2SStefano Zampini     }
1320ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1321ca92afb2SStefano Zampini   }
13224f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1323674ae819SStefano Zampini   PetscFunctionReturn(0);
1324674ae819SStefano Zampini }
1325674ae819SStefano Zampini 
1326674ae819SStefano Zampini #undef __FUNCT__
1327f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1328f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
13296bfb1811SStefano Zampini {
13306bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
13316bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
13326bfb1811SStefano Zampini   VecType        impVecType;
13334f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
13346bfb1811SStefano Zampini   PetscErrorCode ierr;
13356bfb1811SStefano Zampini 
13366bfb1811SStefano Zampini   PetscFunctionBegin;
1337f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
1338019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1339f4ddd8eeSStefano Zampini   }
1340e7b262bdSStefano Zampini   /* get sizes */
13414f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1342b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
13436bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1344e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1345e7b262bdSStefano Zampini   /* R nodes */
1346e7b262bdSStefano Zampini   old_size = -1;
1347e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1348e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1349e7b262bdSStefano Zampini   }
1350e7b262bdSStefano Zampini   if (n_R != old_size) {
1351e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1352e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
13536bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
13546bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
13556bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
13566bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1357e7b262bdSStefano Zampini   }
1358e7b262bdSStefano Zampini   /* local primal dofs */
1359e7b262bdSStefano Zampini   old_size = -1;
1360e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1361e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1362e7b262bdSStefano Zampini   }
1363e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1364e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
136583b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1366e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
13676bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1368e7b262bdSStefano Zampini   }
1369e7b262bdSStefano Zampini   /* local explicit constraints */
1370e7b262bdSStefano Zampini   old_size = -1;
1371e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1372e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1373e7b262bdSStefano Zampini   }
1374e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1375e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
137683b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
137783b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
137883b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
137983b7ccabSStefano Zampini   }
13806bfb1811SStefano Zampini   PetscFunctionReturn(0);
13816bfb1811SStefano Zampini }
13826bfb1811SStefano Zampini 
13836bfb1811SStefano Zampini #undef __FUNCT__
138447f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
138547f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
138688ebb749SStefano Zampini {
138725084f0cSStefano Zampini   PetscErrorCode  ierr;
138825084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
138988ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
139088ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1391d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
139225084f0cSStefano Zampini   /* submatrices of local problem */
139380677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
1394019a44ceSStefano Zampini   /* submatrices of benign trick */
1395d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
139606656605SStefano Zampini   /* submatrices of local coarse problem */
139706656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
139825084f0cSStefano Zampini   /* working matrices */
139906656605SStefano Zampini   Mat             C_CR;
140025084f0cSStefano Zampini   /* additional working stuff */
140106656605SStefano Zampini   PC              pc_R;
14024f1b2e48SStefano Zampini   Mat             F;
1403a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
140406656605SStefano Zampini 
140525084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
140606656605SStefano Zampini   PetscScalar     *work;
140706656605SStefano Zampini   PetscInt        *idx_V_B;
1408ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
140906656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1410ffd830a3SStefano Zampini 
141125084f0cSStefano Zampini   /* some shortcuts to scalars */
141206656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
141388ebb749SStefano Zampini 
141488ebb749SStefano Zampini   PetscFunctionBegin;
1415ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1416ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1417ffd830a3SStefano Zampini   }
1418ffd830a3SStefano Zampini 
1419ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1420b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
14214f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1422b371cd4fSStefano Zampini   n_B = pcis->n_B;
1423b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
142488ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
142588ebb749SStefano Zampini 
142688ebb749SStefano Zampini   /* vertices in boundary numbering */
1427785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
14280e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
142988ebb749SStefano Zampini   if (i != n_vertices) {
143022d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
143188ebb749SStefano Zampini   }
143288ebb749SStefano Zampini 
143306656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1434019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
143506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
143606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
143706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
143806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
143906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
144006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
144106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
144206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
144306656605SStefano Zampini 
144406656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
144506656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
144606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
144706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
144806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1449ffd830a3SStefano Zampini   lda_rhs = n_R;
1450a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
145106656605SStefano Zampini   if (isLU || isILU || isCHOL) {
145206656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1453df4d28bfSStefano Zampini   } else if (sub_schurs->reuse_solver) {
1454df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1455d62866d3SStefano Zampini     MatFactorType      type;
1456d62866d3SStefano Zampini 
1457df4d28bfSStefano Zampini     F = reuse_solver->F;
14586816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1459d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1460ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
1461df4d28bfSStefano Zampini     need_benign_correction = !!reuse_solver->benign_n;
146206656605SStefano Zampini   } else {
146306656605SStefano Zampini     F = NULL;
146406656605SStefano Zampini   }
146506656605SStefano Zampini 
1466ffd830a3SStefano Zampini   /* allocate workspace */
1467ffd830a3SStefano Zampini   n = 0;
1468ffd830a3SStefano Zampini   if (n_constraints) {
1469ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1470ffd830a3SStefano Zampini   }
1471ffd830a3SStefano Zampini   if (n_vertices) {
1472ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1473ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1474ffd830a3SStefano Zampini   }
1475ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1476ffd830a3SStefano Zampini 
147788ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
147888ebb749SStefano Zampini   if (n_constraints) {
147906656605SStefano Zampini     Mat         M1,M2,M3;
148080677318SStefano Zampini     Mat         auxmat;
148106656605SStefano Zampini     IS          is_aux;
148280677318SStefano Zampini     PetscScalar *array,*array2;
148306656605SStefano Zampini 
1484f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
148580677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
148688ebb749SStefano Zampini 
148725084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
148825084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
14898ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
149080677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
149188ebb749SStefano Zampini 
149280677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
149380677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1494ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
149588ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
149606656605SStefano Zampini       const PetscScalar *row_cmat_values;
149706656605SStefano Zampini       const PetscInt    *row_cmat_indices;
149806656605SStefano Zampini       PetscInt          size_of_constraint,j;
149988ebb749SStefano Zampini 
150006656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
150106656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1502ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
150306656605SStefano Zampini       }
150406656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
150506656605SStefano Zampini     }
1506ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
150706656605SStefano Zampini     if (F) {
150806656605SStefano Zampini       Mat B;
150906656605SStefano Zampini 
1510ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1511a3df083aSStefano Zampini       if (need_benign_correction) {
1512a3df083aSStefano Zampini         PetscScalar        *marr;
1513df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1514a3df083aSStefano Zampini 
1515a3df083aSStefano Zampini         ierr = MatDenseGetArray(B,&marr);CHKERRQ(ierr);
1516a3df083aSStefano Zampini         for (i=0;i<n_constraints;i++) {
1517a3df083aSStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1518df4d28bfSStefano Zampini           ierr = PCBDDCReuseSolversChangeInterior(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE);CHKERRQ(ierr);
1519a3df083aSStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1520a3df083aSStefano Zampini         }
1521a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(B,&marr);CHKERRQ(ierr);
1522a3df083aSStefano Zampini       }
152380677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1524a3df083aSStefano Zampini       if (need_benign_correction) {
1525a3df083aSStefano Zampini         PetscScalar        *marr;
1526df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1527a3df083aSStefano Zampini 
1528a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1529a3df083aSStefano Zampini         for (i=0;i<n_constraints;i++) {
1530a3df083aSStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1531df4d28bfSStefano Zampini           ierr = PCBDDCReuseSolversChangeInterior(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE);CHKERRQ(ierr);
1532a3df083aSStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1533a3df083aSStefano Zampini         }
1534a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1535a3df083aSStefano Zampini       }
153606656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
153706656605SStefano Zampini     } else {
153880677318SStefano Zampini       PetscScalar *marr;
153980677318SStefano Zampini 
154080677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
154106656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1542ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1543ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
154406656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
154506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
154606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
154706656605SStefano Zampini       }
154880677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
154906656605SStefano Zampini     }
155080677318SStefano Zampini     if (!pcbddc->switch_static) {
155180677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
155280677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
155380677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
155480677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1555ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
155680677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
155780677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155880677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155980677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
156080677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
156180677318SStefano Zampini       }
156280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
156380677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
156480677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
156580677318SStefano Zampini     } else {
1566ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1567ffd830a3SStefano Zampini         IS dummy;
1568ffd830a3SStefano Zampini 
1569ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
1570ffd830a3SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,dummy,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1571ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1572ffd830a3SStefano Zampini       } else {
157380677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
157480677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1575ffd830a3SStefano Zampini       }
157625084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
157780677318SStefano Zampini     }
157880677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
157980677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
158080677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
158106656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
158206656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
158380677318SStefano Zampini     if (isCHOL) {
158480677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
158580677318SStefano Zampini     } else {
158625084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
158780677318SStefano Zampini     }
158880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
158906656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
159025084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
159125084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
159225084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
159380677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
159480677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
159580677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
159606656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
159706656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1598f4ddd8eeSStefano Zampini   }
159988ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
16004f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
1601d16cbb6bSStefano Zampini     IS        dummy;
1602d16cbb6bSStefano Zampini     Mat       B0_R;
1603d16cbb6bSStefano Zampini     PetscReal norm;
1604d16cbb6bSStefano Zampini 
16054f1b2e48SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
16064f1b2e48SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
1607d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
1608d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
1609d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
1610d16cbb6bSStefano Zampini     }
1611d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
1612d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1613d16cbb6bSStefano Zampini   }
1614d16cbb6bSStefano Zampini 
161588ebb749SStefano Zampini   if (n_vertices) {
161606656605SStefano Zampini     IS is_aux;
16173a50541eSStefano Zampini 
1618df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
16196816873aSStefano Zampini       IS tis;
16206816873aSStefano Zampini 
16216816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
16226816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
16236816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
16246816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
16256816873aSStefano Zampini     } else {
16263a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
16276816873aSStefano Zampini     }
16289577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
16299577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
163004708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
16314f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1632019a44ceSStefano Zampini       IS dummy;
1633019a44ceSStefano Zampini 
16344f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
16354f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1636019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1637019a44ceSStefano Zampini     }
163825084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
163988ebb749SStefano Zampini   }
164088ebb749SStefano Zampini 
164188ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1642f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
164306656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
164406656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
164506656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
164606656605SStefano Zampini     }
1647f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
164806656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
164906656605SStefano Zampini       PetscScalar *marray;
165006656605SStefano Zampini 
165106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
165206656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1653f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1654f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1655f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1656f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1657f4ddd8eeSStefano Zampini     }
1658f4ddd8eeSStefano Zampini   }
165906656605SStefano Zampini 
1660f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
166106656605SStefano Zampini     PetscScalar *marray;
166288ebb749SStefano Zampini 
166306656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
16648eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
166506656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
166688ebb749SStefano Zampini     }
16673301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
166806656605SStefano Zampini       n *= 2;
166988ebb749SStefano Zampini     }
167006656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
167106656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
167206656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
16738eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
167406656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
167506656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
167688ebb749SStefano Zampini     }
16773301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
167806656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
16798eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
168006656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
168106656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
168288ebb749SStefano Zampini       }
168388ebb749SStefano Zampini     } else {
1684c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1685c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
16861b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1687c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1688c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1689c0553b1fSStefano Zampini       }
169088ebb749SStefano Zampini     }
169106656605SStefano Zampini   }
1692019a44ceSStefano Zampini 
169306656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
16944f1b2e48SStefano Zampini   p0_lidx_I = NULL;
16954f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1696d12edf2fSStefano Zampini     const PetscInt *idxs;
1697d12edf2fSStefano Zampini 
1698d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
16994f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
17004f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
17014f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
17024f1b2e48SStefano Zampini     }
1703d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1704d12edf2fSStefano Zampini   }
1705d16cbb6bSStefano Zampini 
170606656605SStefano Zampini   /* vertices */
170706656605SStefano Zampini   if (n_vertices) {
170816f15bc4SStefano Zampini 
1709ffd830a3SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
171004708bb6SStefano Zampini 
171116f15bc4SStefano Zampini     if (n_R) {
171214393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
171306656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
171416f15bc4SStefano Zampini       PetscScalar  *x,*y;
171504708bb6SStefano Zampini       PetscBool    isseqaij;
171606656605SStefano Zampini 
171721eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
171814393ed6SStefano Zampini       if (need_benign_correction) {
171914393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
172014393ed6SStefano Zampini         IS                     is_p0;
172114393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
172214393ed6SStefano Zampini 
172314393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
172414393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
172514393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
172614393ed6SStefano Zampini         if (n != pcbddc->benign_n) {
172714393ed6SStefano Zampini           SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %d != %d\n",n,pcbddc->benign_n);
172814393ed6SStefano Zampini         }
172914393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
173014393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
173114393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
173214393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
173314393ed6SStefano Zampini       }
173414393ed6SStefano Zampini 
1735ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
1736ffd830a3SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
1737ffd830a3SStefano Zampini       } else {
1738ca92afb2SStefano Zampini         PetscScalar    *av,*array;
1739ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
1740ca92afb2SStefano Zampini         PetscInt       n;
1741ca92afb2SStefano Zampini         PetscBool      flg_row;
1742ffd830a3SStefano Zampini 
1743ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
1744ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
1745ca92afb2SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
1746ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1747ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
1748ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
1749ca92afb2SStefano Zampini           PetscInt j;
1750ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
1751ffd830a3SStefano Zampini         }
1752ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1753ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1754ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
1755ffd830a3SStefano Zampini       }
1756ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
175714393ed6SStefano Zampini       if (F) {
1758a3df083aSStefano Zampini         if (need_benign_correction) {
1759df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1760a3df083aSStefano Zampini           PetscScalar        *marr;
1761a3df083aSStefano Zampini 
1762a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
176314393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
176414393ed6SStefano Zampini 
176514393ed6SStefano Zampini                  | 0 0  0 | (V)
176614393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
176714393ed6SStefano Zampini                  | 0 0 -1 | (p0)
176814393ed6SStefano Zampini 
176914393ed6SStefano Zampini           */
1770df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
177114393ed6SStefano Zampini             const PetscScalar *vals;
177214393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
177314393ed6SStefano Zampini             PetscInt          n,j,nz;
177414393ed6SStefano Zampini 
1775df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1776df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
177714393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
177814393ed6SStefano Zampini             for (j=0;j<n;j++) {
177914393ed6SStefano Zampini               PetscScalar val = vals[j];
178014393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
178114393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
178214393ed6SStefano Zampini             }
178314393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
1784df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
178514393ed6SStefano Zampini           }
178614393ed6SStefano Zampini           /* need to correct the rhs */
1787a3df083aSStefano Zampini           for (i=0;i<n_vertices;i++) {
1788a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1789df4d28bfSStefano Zampini             ierr = PCBDDCReuseSolversChangeInterior(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE);CHKERRQ(ierr);
1790a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1791a3df083aSStefano Zampini           }
1792a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
1793a3df083aSStefano Zampini         }
179406656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
179514393ed6SStefano Zampini         /* need to correct the solution */
1796a3df083aSStefano Zampini         if (need_benign_correction) {
1797df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1798a3df083aSStefano Zampini           PetscScalar        *marr;
1799a3df083aSStefano Zampini 
1800a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
1801a3df083aSStefano Zampini           for (i=0;i<n_vertices;i++) {
1802a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1803df4d28bfSStefano Zampini             ierr = PCBDDCReuseSolversChangeInterior(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE);CHKERRQ(ierr);
1804a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1805a3df083aSStefano Zampini           }
1806a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
1807a3df083aSStefano Zampini         }
180806656605SStefano Zampini       } else {
180906656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
181006656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
1811ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
1812ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
181306656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
181406656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
181506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
181606656605SStefano Zampini         }
181706656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
181806656605SStefano Zampini       }
181980677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1820ffd830a3SStefano Zampini       /* S_VV and S_CV */
182106656605SStefano Zampini       if (n_constraints) {
182206656605SStefano Zampini         Mat B;
182380677318SStefano Zampini 
1824ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
182580677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
1826ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1827ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
182880677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
182980677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183080677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
183180677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
183280677318SStefano Zampini         }
1833ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
183480677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
183580677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
1836ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
183780677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
183806656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
1839ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
1840ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
184106656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
184206656605SStefano Zampini       }
184304708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
184404708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
184504708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
184604708bb6SStefano Zampini       }
1847ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1848ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
1849ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
1850ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
1851ffd830a3SStefano Zampini       }
185206656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
185314393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
185414393ed6SStefano Zampini       if (need_benign_correction) {
1855df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
185614393ed6SStefano Zampini         PetscScalar      *marr,*sums;
185714393ed6SStefano Zampini 
185814393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
185914393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
1860df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
186114393ed6SStefano Zampini           const PetscScalar *vals;
186214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
186314393ed6SStefano Zampini           PetscInt          n,j,nz;
186414393ed6SStefano Zampini 
1865df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1866df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
186714393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
186814393ed6SStefano Zampini             PetscInt k;
186914393ed6SStefano Zampini             sums[j] = 0.;
187014393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
187114393ed6SStefano Zampini           }
187214393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
187314393ed6SStefano Zampini           for (j=0;j<n;j++) {
187414393ed6SStefano Zampini             PetscScalar val = vals[j];
187514393ed6SStefano Zampini             PetscInt k;
187614393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
187714393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
187814393ed6SStefano Zampini             }
187914393ed6SStefano Zampini           }
188014393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
1881df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
188214393ed6SStefano Zampini         }
188314393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
188414393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
188514393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
188614393ed6SStefano Zampini       }
188780677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
188806656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
188906656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
189006656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
189106656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
189206656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
189306656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
189406656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1895d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1896019a44ceSStefano Zampini     } else {
1897d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1898d16cbb6bSStefano Zampini     }
18994f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1900019a44ceSStefano Zampini       const PetscScalar *vals;
1901019a44ceSStefano Zampini       const PetscInt    *idxs;
19024f1b2e48SStefano Zampini       PetscInt          n,j,primal_idx;
1903019a44ceSStefano Zampini 
19044f1b2e48SStefano Zampini       ierr = MatGetRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
19054f1b2e48SStefano Zampini       primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + i;
1906d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
19074f1b2e48SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+idxs[j]] = vals[j];
19084f1b2e48SStefano Zampini         coarse_submat_vals[idxs[j]*pcbddc->local_primal_size+primal_idx] = vals[j];
1909019a44ceSStefano Zampini       }
19104f1b2e48SStefano Zampini       ierr = MatRestoreRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
191116f15bc4SStefano Zampini     }
191221eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1913d16cbb6bSStefano Zampini 
191406656605SStefano Zampini     /* coarse basis functions */
191506656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
191616f15bc4SStefano Zampini       PetscScalar *y;
191716f15bc4SStefano Zampini 
1918ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
191906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
192006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
192106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
192206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
192306656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
192406656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
192506656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
192606656605SStefano Zampini 
192706656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
19284f1b2e48SStefano Zampini         PetscInt j;
19294f1b2e48SStefano Zampini 
193006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
193106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
193206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
193306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
193406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
19354f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
193606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
193706656605SStefano Zampini       }
193806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
193906656605SStefano Zampini     }
194004708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
194104708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
194206656605SStefano Zampini   }
194306656605SStefano Zampini 
194406656605SStefano Zampini   if (n_constraints) {
194506656605SStefano Zampini     Mat B;
194606656605SStefano Zampini 
1947ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
194806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
194980677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
195006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
195106656605SStefano Zampini     if (n_vertices) {
195280677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
195380677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
195480677318SStefano Zampini       } else {
195580677318SStefano Zampini         Mat S_VCt;
195680677318SStefano Zampini 
1957ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
1958ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
1959ffd830a3SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B);CHKERRQ(ierr);
1960ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
1961ffd830a3SStefano Zampini         }
196280677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
196380677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
196480677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
196580677318SStefano Zampini       }
196606656605SStefano Zampini     }
196706656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
196806656605SStefano Zampini     /* coarse basis functions */
196906656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
197006656605SStefano Zampini       PetscScalar *y;
197106656605SStefano Zampini 
1972ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
197306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
197406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
197506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
197606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
197706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
197806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
197906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
19804f1b2e48SStefano Zampini         PetscInt j;
19814f1b2e48SStefano Zampini 
198206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
198306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
198406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
198506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
198606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
19874f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
198806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
198906656605SStefano Zampini       }
199006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
199106656605SStefano Zampini     }
199206656605SStefano Zampini   }
199380677318SStefano Zampini   if (n_constraints) {
199480677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
199580677318SStefano Zampini   }
19964f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
1997019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1998019a44ceSStefano Zampini 
199906656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
20003301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
2001ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
2002ffd830a3SStefano Zampini     PetscScalar *marray;
200306656605SStefano Zampini 
200406656605SStefano Zampini     if (n_constraints) {
2005ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
200606656605SStefano Zampini 
2007ffd830a3SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
200806656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
2009ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
201016f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
201106656605SStefano Zampini       if (n_vertices) {
2012ffd830a3SStefano Zampini         Mat S_VCT;
201306656605SStefano Zampini 
201406656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
2015ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
201616f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
201706656605SStefano Zampini       }
2018ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
201906656605SStefano Zampini     }
202016f15bc4SStefano Zampini     if (n_vertices && n_R) {
2021ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2022ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2023ffd830a3SStefano Zampini       PetscInt       n;
2024ffd830a3SStefano Zampini       PetscBool      flg_row;
202506656605SStefano Zampini 
2026ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2027ffd830a3SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
2028ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2029ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2030ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2031ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2032ffd830a3SStefano Zampini         PetscInt j;
2033ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2034ffd830a3SStefano Zampini       }
2035ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2036ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2037ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
203806656605SStefano Zampini     }
203906656605SStefano Zampini 
2040ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2041ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2042ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2043ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2044ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
204506656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
204606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
204706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
204806656605SStefano Zampini     }
2049ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2050ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2051ffd830a3SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2052ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2053ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2054ffd830a3SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2055ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2056ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
205706656605SStefano Zampini     }
2058ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
205906656605SStefano Zampini     /* coarse basis functions */
206006656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
206106656605SStefano Zampini       PetscScalar *y;
206206656605SStefano Zampini 
2063ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
206406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
206506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
206606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
206706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
206806656605SStefano Zampini       if (i<n_vertices) {
206906656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
207006656605SStefano Zampini       }
207106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
207206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
207306656605SStefano Zampini 
207406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
207506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
207606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
207706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
207806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
207906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
208006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
208106656605SStefano Zampini       }
208206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
208306656605SStefano Zampini     }
2084ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2085ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
208606656605SStefano Zampini   }
2087d62866d3SStefano Zampini   /* free memory */
208888ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
208906656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
209006656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
209106656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
209206656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2093d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2094d62866d3SStefano Zampini   if (n_vertices) {
2095d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2096d62866d3SStefano Zampini   }
2097d62866d3SStefano Zampini   if (n_constraints) {
2098d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2099d62866d3SStefano Zampini   }
210088ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
210188ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
210288ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2103d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
210488ebb749SStefano Zampini     Mat         coarse_sub_mat;
210525084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
210688ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
210788ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
210888ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
21098bec7fa6SStefano Zampini     Mat         C_B,CPHI;
21108bec7fa6SStefano Zampini     IS          is_dummy;
21118bec7fa6SStefano Zampini     Vec         mones;
211288ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
211388ebb749SStefano Zampini     PetscReal   real_value;
211488ebb749SStefano Zampini 
2115a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2116a3df083aSStefano Zampini       Mat A;
2117a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2118a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2119a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2120a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2121a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2122a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2123a3df083aSStefano Zampini     } else {
212488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
212588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
212688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
212788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2128a3df083aSStefano Zampini     }
212988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
213088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2131ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
213288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
213388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
213488ebb749SStefano Zampini     }
213588ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
213688ebb749SStefano Zampini 
213725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
21383301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
213925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2140ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
214188ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
214288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
214388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
214488ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
214588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
214688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
214788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
214888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
214988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
215088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
215188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
215288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
215388ebb749SStefano Zampini     } else {
215488ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
215588ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
215688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
215788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
215888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
215988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
216088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
216188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
216288ebb749SStefano Zampini     }
216388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
216488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
216588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
216688ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
21674f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2168d12edf2fSStefano Zampini       Mat         B0_I,B0_B,B0_BPHI,B0_IPHI;
2169d12edf2fSStefano Zampini       PetscScalar *data,*data2;
21704f1b2e48SStefano Zampini       PetscInt    j;
2171d12edf2fSStefano Zampini 
21724f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
21734f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
21744f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
2175d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
2176d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2177d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2178d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
21794f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
21804f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2181d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
21824f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
21834f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
21844f1b2e48SStefano Zampini         }
2185d12edf2fSStefano Zampini       }
2186d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2187d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2188d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2189d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2190d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2191d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
2192d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
2193d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2194d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
2195d12edf2fSStefano Zampini     }
2196d12edf2fSStefano Zampini #if 0
2197d12edf2fSStefano Zampini   {
2198d12edf2fSStefano Zampini     PetscViewer viewer;
2199d12edf2fSStefano Zampini     char filename[256];
2200ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2201d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2202d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2203ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2204ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2205ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2206d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
2207ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2208ffd830a3SStefano Zampini     ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
2209ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2210ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2211ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2212ffd830a3SStefano Zampini     }
2213ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2214ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2215ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2216ffd830a3SStefano Zampini     }
2217ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_B) {
2218ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2219ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2220ffd830a3SStefano Zampini     }
2221d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2222d12edf2fSStefano Zampini   }
2223d12edf2fSStefano Zampini #endif
222481d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
22258bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
22261575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
222706656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
22288bec7fa6SStefano Zampini 
22298bec7fa6SStefano Zampini     /* check constraints */
22304f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
22318bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
22328bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
22338bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
22348bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
22358bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
22368bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
22378bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2238bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2239ffd830a3SStefano Zampini       if (!pcbddc->symmetric_primal) {
2240bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2241bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2242bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2243bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2244bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
224588ebb749SStefano Zampini       }
22468bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
22478bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
22488bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
22498bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
2250d12edf2fSStefano Zampini     }
225125084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
225288ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
225388ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
225488ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
225588ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
225688ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
225788ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
225888ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
225988ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
226088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
226188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2262ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
226388ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
226488ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
226588ebb749SStefano Zampini     }
226688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
226788ebb749SStefano Zampini   }
22688629588bSStefano Zampini   /* get back data */
22698629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
227088ebb749SStefano Zampini   PetscFunctionReturn(0);
227188ebb749SStefano Zampini }
227288ebb749SStefano Zampini 
227388ebb749SStefano Zampini #undef __FUNCT__
2274d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2275d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2276aa0d41d4SStefano Zampini {
2277d65f70fdSStefano Zampini   Mat            *work_mat;
2278d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2279d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2280d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
2281aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2282aa0d41d4SStefano Zampini 
2283aa0d41d4SStefano Zampini   PetscFunctionBegin;
2284d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2285d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2286d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2287d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2288aa0d41d4SStefano Zampini 
2289d65f70fdSStefano Zampini   if (!rsorted) {
2290906d46d4SStefano Zampini     const PetscInt *idxs;
2291906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2292aa0d41d4SStefano Zampini 
2293d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2294d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2295d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2296d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2297aa0d41d4SStefano Zampini     }
2298d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2299d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2300d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2301d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2302aa0d41d4SStefano Zampini     }
2303d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2304d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2305d65f70fdSStefano Zampini   } else {
2306d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2307d65f70fdSStefano Zampini     isrow_s = isrow;
2308aa0d41d4SStefano Zampini   }
2309906d46d4SStefano Zampini 
2310d65f70fdSStefano Zampini   if (!csorted) {
2311d65f70fdSStefano Zampini     if (isrow == iscol) {
2312d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2313d65f70fdSStefano Zampini       iscol_s = isrow_s;
2314d65f70fdSStefano Zampini     } else {
2315d65f70fdSStefano Zampini       const PetscInt *idxs;
2316d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
2317906d46d4SStefano Zampini 
2318d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2319d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2320d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2321d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2322d65f70fdSStefano Zampini       }
2323d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2324d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2325d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2326d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2327d65f70fdSStefano Zampini       }
2328d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2329d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2330d65f70fdSStefano Zampini     }
2331d65f70fdSStefano Zampini   } else {
2332d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2333d65f70fdSStefano Zampini     iscol_s = iscol;
2334d65f70fdSStefano Zampini   }
2335d65f70fdSStefano Zampini 
2336d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2337d65f70fdSStefano Zampini 
2338d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2339906d46d4SStefano Zampini     Mat      new_mat;
2340d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2341906d46d4SStefano Zampini 
2342d65f70fdSStefano Zampini     if (!rsorted) {
2343d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2344d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2345d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2346d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2347906d46d4SStefano Zampini       }
2348d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2349d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2350d65f70fdSStefano Zampini     } else {
2351d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2352906d46d4SStefano Zampini     }
2353d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2354d65f70fdSStefano Zampini 
2355d65f70fdSStefano Zampini     if (!csorted) {
2356d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2357d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2358d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2359d65f70fdSStefano Zampini       } else {
2360d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2361d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2362d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2363d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2364d65f70fdSStefano Zampini         }
2365d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2366d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2367d65f70fdSStefano Zampini       }
2368d65f70fdSStefano Zampini     } else {
2369d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2370d65f70fdSStefano Zampini     }
2371d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2372d65f70fdSStefano Zampini 
2373d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2374d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2375d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2376d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2377d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2378d65f70fdSStefano Zampini   }
2379d65f70fdSStefano Zampini 
2380d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2381d65f70fdSStefano Zampini   *B = work_mat[0];
2382d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2383d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2384d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2385d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2386d65f70fdSStefano Zampini }
2387d65f70fdSStefano Zampini 
2388d65f70fdSStefano Zampini #undef __FUNCT__
23895e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
23905e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2391aa0d41d4SStefano Zampini {
2392aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
23935e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2394d65f70fdSStefano Zampini   Mat            new_mat;
23955e8657edSStefano Zampini   IS             is_local,is_global;
2396d65f70fdSStefano Zampini   PetscInt       local_size;
2397d65f70fdSStefano Zampini   PetscBool      isseqaij;
2398aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2399aa0d41d4SStefano Zampini 
2400aa0d41d4SStefano Zampini   PetscFunctionBegin;
2401aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
24025e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
24035e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2404b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2405aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2406d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2407aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2408906d46d4SStefano Zampini 
2409906d46d4SStefano Zampini   /* check */
2410906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2411906d46d4SStefano Zampini     Vec       x,x_change;
2412906d46d4SStefano Zampini     PetscReal error;
2413906d46d4SStefano Zampini 
24145e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2415906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
24165e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2417e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2418e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2419d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2420e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2421e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2422906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2423906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2424906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2425906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2426906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2427906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2428906d46d4SStefano Zampini   }
2429906d46d4SStefano Zampini 
243022d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
24319b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
243222d5777bSStefano Zampini   if (isseqaij) {
24331cf9b237SStefano Zampini     Mat M;
24341cf9b237SStefano Zampini 
24351cf9b237SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
24361cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
24371cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2438aa0d41d4SStefano Zampini   } else {
24391cf9b237SStefano Zampini     Mat work_mat,M;
24401cf9b237SStefano Zampini 
2441aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
24421cf9b237SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
24431cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
24441cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2445aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2446aa0d41d4SStefano Zampini   }
24473301b35fSStefano Zampini   if (matis->A->symmetric_set) {
24483301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2449e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
24503301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2451e496cd5dSStefano Zampini #endif
24523301b35fSStefano Zampini   }
245345a1bb75SStefano Zampini   /*
245445a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2455d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
245645a1bb75SStefano Zampini   */
2457d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2458aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2459aa0d41d4SStefano Zampini }
2460aa0d41d4SStefano Zampini 
2461aa0d41d4SStefano Zampini #undef __FUNCT__
2462a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
24638ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2464a64d13efSStefano Zampini {
2465a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2466a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2467d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
246853892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
24693a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
24703a50541eSStefano Zampini   PetscInt        vbs,bs;
24716816873aSStefano Zampini   PetscBT         bitmask=NULL;
2472a64d13efSStefano Zampini   PetscErrorCode  ierr;
2473a64d13efSStefano Zampini 
2474a64d13efSStefano Zampini   PetscFunctionBegin;
2475b23d619eSStefano Zampini   /*
2476b23d619eSStefano Zampini     No need to setup local scatters if
2477b23d619eSStefano Zampini       - primal space is unchanged
2478b23d619eSStefano Zampini         AND
2479b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2480b23d619eSStefano Zampini         AND
2481b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2482b23d619eSStefano Zampini   */
2483b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2484f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2485f4ddd8eeSStefano Zampini   }
2486f4ddd8eeSStefano Zampini   /* destroy old objects */
2487f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2488f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2489f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2490a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2491b371cd4fSStefano Zampini   n_B = pcis->n_B;
2492b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2493b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
24943a50541eSStefano Zampini 
2495a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
24966816873aSStefano Zampini 
249753892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2498df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
2499854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2500a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2501a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
25020e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2503a64d13efSStefano Zampini     }
2504a64d13efSStefano Zampini 
2505a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
25064641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
25076816873aSStefano Zampini         idx_R_local[n_R++] = i;
2508a64d13efSStefano Zampini       }
2509a64d13efSStefano Zampini     }
2510df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2511df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
25126816873aSStefano Zampini 
2513df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2514df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
25156816873aSStefano Zampini   }
25163a50541eSStefano Zampini 
25173a50541eSStefano Zampini   /* Block code */
25183a50541eSStefano Zampini   vbs = 1;
25193a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
25203a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
25213a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
25223a50541eSStefano Zampini     PetscInt  *vary;
2523df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
2524785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
25253a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2526d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2527d3df7717SStefano 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 */
25280e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2529d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
25303a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
25313a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
25323a50541eSStefano Zampini           break;
25333a50541eSStefano Zampini         }
25343a50541eSStefano Zampini       }
2535d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2536d3df7717SStefano Zampini     } else {
2537d3df7717SStefano Zampini       /* Verify directly the R set */
2538d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2539d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2540d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2541d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2542d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2543d3df7717SStefano Zampini             break;
2544d3df7717SStefano Zampini           }
2545d3df7717SStefano Zampini         }
2546d3df7717SStefano Zampini       }
2547d3df7717SStefano Zampini     }
25483a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
25493a50541eSStefano Zampini       vbs = bs;
25503a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
25513a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
25523a50541eSStefano Zampini       }
25533a50541eSStefano Zampini     }
25543a50541eSStefano Zampini   }
25553a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2556df4d28bfSStefano Zampini   if (sub_schurs->reuse_solver) {
2557df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
255853892102SStefano Zampini 
2559df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2560df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
256153892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2562df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
256353892102SStefano Zampini   } else {
25643a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
256553892102SStefano Zampini   }
2566a64d13efSStefano Zampini 
2567a64d13efSStefano Zampini   /* print some info if requested */
2568a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2569a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2570a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
25711575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2572a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2573a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
25744f1b2e48SStefano 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);
2575a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2576a64d13efSStefano Zampini   }
2577a64d13efSStefano Zampini 
2578a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
2579df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
25806816873aSStefano Zampini     IS       is_aux1,is_aux2;
25816816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
25826816873aSStefano Zampini 
25833a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2584854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2585854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2586a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
25874641a718SStefano Zampini     for (i=0; i<n_D; i++) {
25884641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
25894641a718SStefano Zampini     }
2590a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2591a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
25924641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
25934641a718SStefano Zampini         aux_array1[j++] = i;
2594a64d13efSStefano Zampini       }
2595a64d13efSStefano Zampini     }
2596a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2597a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2598a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
25994641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
26004641a718SStefano Zampini         aux_array2[j++] = i;
2601a64d13efSStefano Zampini       }
2602a64d13efSStefano Zampini     }
2603a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2604a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2605a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2606a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2607a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2608a64d13efSStefano Zampini 
26098eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2610785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2611a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
26124641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
26134641a718SStefano Zampini           aux_array1[j++] = i;
2614a64d13efSStefano Zampini         }
2615a64d13efSStefano Zampini       }
2616a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2617a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2618a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2619a64d13efSStefano Zampini     }
26204641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
26213a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2622d62866d3SStefano Zampini   } else {
2623df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
26246816873aSStefano Zampini     IS                 tis;
26256816873aSStefano Zampini     PetscInt           schur_size;
26266816873aSStefano Zampini 
2627df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
26286816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
2629df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
26306816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
26316816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
26326816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
26336816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
26346816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2635d62866d3SStefano Zampini     }
2636d62866d3SStefano Zampini   }
2637a64d13efSStefano Zampini   PetscFunctionReturn(0);
2638a64d13efSStefano Zampini }
2639a64d13efSStefano Zampini 
2640304d26faSStefano Zampini 
2641304d26faSStefano Zampini #undef __FUNCT__
2642304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2643684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2644304d26faSStefano Zampini {
2645304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2646304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2647304d26faSStefano Zampini   PC             pc_temp;
2648304d26faSStefano Zampini   Mat            A_RR;
2649f4ddd8eeSStefano Zampini   MatReuse       reuse;
2650304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2651304d26faSStefano Zampini   PetscReal      value;
265204708bb6SStefano Zampini   PetscInt       n_D,n_R;
26539577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
2654304d26faSStefano Zampini   PetscErrorCode ierr;
2655e604994aSStefano Zampini   /* prefixes stuff */
2656312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2657e604994aSStefano Zampini   size_t         len;
2658304d26faSStefano Zampini 
2659304d26faSStefano Zampini   PetscFunctionBegin;
2660304d26faSStefano Zampini 
2661e604994aSStefano Zampini   /* compute prefixes */
2662e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2663e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2664e604994aSStefano Zampini   if (!pcbddc->current_level) {
2665e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2666e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2667e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2668e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2669e604994aSStefano Zampini   } else {
2670e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2671312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2672e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2673e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2674312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2675312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
267634d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
267734d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2678e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2679e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2680e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
2681e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
2682e604994aSStefano Zampini   }
2683e604994aSStefano Zampini 
2684304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
2685684f6988SStefano Zampini   if (dirichlet) {
2686d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2687a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit && pcbddc->dbg_flag) {
2688a3df083aSStefano Zampini       Mat    A_IIn;
2689a3df083aSStefano Zampini 
2690a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
2691a3df083aSStefano Zampini       ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
2692a3df083aSStefano Zampini       pcis->A_II = A_IIn;
2693a3df083aSStefano Zampini     }
26943301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
26953301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2696964fefecSStefano Zampini     }
2697ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
2698964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
2699304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
2700304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
2701304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
2702304d26faSStefano Zampini       /* default */
2703304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
2704e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
27059577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2706304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
27079577ea80SStefano Zampini       if (issbaij) {
27089577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
27099577ea80SStefano Zampini       } else {
2710304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
27119577ea80SStefano Zampini       }
2712304d26faSStefano Zampini       /* Allow user's customization */
2713304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
2714304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2715304d26faSStefano Zampini     }
2716d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
2717df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
2718df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2719d62866d3SStefano Zampini 
2720df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
2721d5574798SStefano Zampini     }
2722304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2723304d26faSStefano Zampini     if (!n_D) {
2724304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
2725304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2726304d26faSStefano Zampini     }
2727304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
2728304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
2729304d26faSStefano Zampini     /* set ksp_D into pcis data */
2730304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
2731304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
2732304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
2733684f6988SStefano Zampini   }
2734304d26faSStefano Zampini 
2735304d26faSStefano Zampini   /* NEUMANN PROBLEM */
2736684f6988SStefano Zampini   A_RR = 0;
2737684f6988SStefano Zampini   if (neumann) {
2738d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
273904708bb6SStefano Zampini     PetscInt        ibs,mbs;
274004708bb6SStefano Zampini     PetscBool       issbaij;
274104708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
2742f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
27438ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
2744f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
2745f4ddd8eeSStefano Zampini       PetscInt nn_R;
274681d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
2747f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2748f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
2749f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
2750f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
2751f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2752f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2753f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
2754727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
2755f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2756f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
2757f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
2758f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
2759f4ddd8eeSStefano Zampini         }
2760f4ddd8eeSStefano Zampini       }
2761f4ddd8eeSStefano Zampini       /* last check */
2762d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
2763f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2764f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2765f4ddd8eeSStefano Zampini       }
2766f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
2767f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
2768f4ddd8eeSStefano Zampini     }
2769f4ddd8eeSStefano Zampini     /* extract A_RR */
2770af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
2771af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
277204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
277304708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
277404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
277504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
277604708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2777af732b37SStefano Zampini       } else {
277804708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
27796816873aSStefano Zampini       }
278004708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
278104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
278204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
278304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
278404708bb6SStefano Zampini       } else {
278504708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
278604708bb6SStefano Zampini       }
278704708bb6SStefano Zampini     }
2788f4ddd8eeSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
27893301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
27903301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
27916816873aSStefano Zampini     }
2792a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit && pcbddc->dbg_flag) {
2793a3df083aSStefano Zampini       Mat A_RRn;
2794a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RRn);CHKERRQ(ierr);
2795a3df083aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2796a3df083aSStefano Zampini       A_RR = A_RRn;
2797a3df083aSStefano Zampini     }
2798f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
2799304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
2800304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
2801304d26faSStefano Zampini       /* default */
2802304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
2803e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
2804304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
28059577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
28069577ea80SStefano Zampini       if (issbaij) {
28079577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
28089577ea80SStefano Zampini       } else {
2809304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
28109577ea80SStefano Zampini       }
2811304d26faSStefano Zampini       /* Allow user's customization */
2812304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
2813304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2814304d26faSStefano Zampini     }
2815304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2816304d26faSStefano Zampini     if (!n_R) {
2817304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2818304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2819304d26faSStefano Zampini     }
2820df4d28bfSStefano Zampini     /* Reuse solver if it is present */
2821df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
2822df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2823d62866d3SStefano Zampini 
2824df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
2825d62866d3SStefano Zampini     }
2826ffd830a3SStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2827304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
2828304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2829684f6988SStefano Zampini   }
28306816873aSStefano Zampini   /* free Neumann problem's matrix */
28316816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2832304d26faSStefano Zampini 
2833304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
28340fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2835684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
2836684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
28371575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2838684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2839684f6988SStefano Zampini     }
2840684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
28410fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
28420fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
28430fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
28440fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
28450fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2846304d26faSStefano Zampini       /* need to be adapted? */
2847b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2848b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2849b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2850304d26faSStefano Zampini       /* print info */
2851304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2852e604994aSStefano 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);
2853304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2854304d26faSStefano Zampini       }
2855b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2856298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2857304d26faSStefano Zampini       }
2858684f6988SStefano Zampini     }
2859684f6988SStefano Zampini     if (neumann) { /* Neumann */
28606816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
28610fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
28620fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
28630fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
28640fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
28650fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2866304d26faSStefano Zampini       /* need to be adapted? */
2867b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2868b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2869304d26faSStefano Zampini       /* print info */
2870304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2871e604994aSStefano 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);
2872304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2873304d26faSStefano Zampini       }
2874b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2875298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2876304d26faSStefano Zampini       }
28770fccc4e9SStefano Zampini     }
2878684f6988SStefano Zampini   }
2879304d26faSStefano Zampini   PetscFunctionReturn(0);
2880304d26faSStefano Zampini }
2881304d26faSStefano Zampini 
2882304d26faSStefano Zampini #undef __FUNCT__
2883ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
288480677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2885674ae819SStefano Zampini {
2886674ae819SStefano Zampini   PetscErrorCode  ierr;
2887674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2888be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2889674ae819SStefano Zampini 
2890674ae819SStefano Zampini   PetscFunctionBegin;
2891df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
289280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
289320c7b377SStefano Zampini   }
289480677318SStefano Zampini   if (!pcbddc->switch_static) {
289580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
289680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
289780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
289820c7b377SStefano Zampini     }
2899df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
290080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
290180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
290220c7b377SStefano Zampini     } else {
2903df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2904be83ff47SStefano Zampini 
2905df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2906df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
290720c7b377SStefano Zampini     }
2908be83ff47SStefano Zampini   } else {
290980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291380677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
291480677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
291580677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
291680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2918674ae819SStefano Zampini     }
2919674ae819SStefano Zampini   }
2920df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
292180677318SStefano Zampini     if (applytranspose) {
292280677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
292380677318SStefano Zampini     } else {
292480677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
292580677318SStefano Zampini     }
2926be83ff47SStefano Zampini   } else {
2927df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2928be83ff47SStefano Zampini 
2929be83ff47SStefano Zampini     if (applytranspose) {
2930df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
2931be83ff47SStefano Zampini     } else {
2932df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
2933be83ff47SStefano Zampini     }
2934be83ff47SStefano Zampini   }
293580677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
293680677318SStefano Zampini   if (!pcbddc->switch_static) {
2937df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
293880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
293980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2940be83ff47SStefano Zampini     } else {
2941df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2942be83ff47SStefano Zampini 
2943df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2944df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2945be83ff47SStefano Zampini     }
294680677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
294780677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
294880677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
294980677318SStefano Zampini     }
295080677318SStefano Zampini   } else {
295180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
295280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
295380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
295480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
295580677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
295680677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
295780677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
295880677318SStefano Zampini     }
295980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2963674ae819SStefano Zampini   }
2964674ae819SStefano Zampini   PetscFunctionReturn(0);
2965674ae819SStefano Zampini }
2966674ae819SStefano Zampini 
2967dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2968674ae819SStefano Zampini #undef __FUNCT__
2969674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2970dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2971674ae819SStefano Zampini {
2972674ae819SStefano Zampini   PetscErrorCode ierr;
2973674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2974674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2975674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2976674ae819SStefano Zampini 
2977674ae819SStefano Zampini   PetscFunctionBegin;
2978dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2979dc359a40SStefano Zampini   if (applytranspose) {
2980674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
29818eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2982dc359a40SStefano Zampini   } else {
2983674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2984674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
298515aaf578SStefano Zampini   }
2986efc2fbd9SStefano Zampini 
2987efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
29884f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2989efc2fbd9SStefano Zampini     PetscScalar *array;
29904f1b2e48SStefano Zampini     PetscInt    j;
2991efc2fbd9SStefano Zampini 
2992efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
29934f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
2994efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2995efc2fbd9SStefano Zampini   }
2996efc2fbd9SStefano Zampini 
299712edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
299812edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
299912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
300012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
300112edc857SStefano Zampini 
30029f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
300312edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
300412edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
300551694757SStefano Zampini     Mat coarse_mat;
3006964fefecSStefano Zampini     Vec rhs,sol;
300751694757SStefano Zampini     MatNullSpace nullsp;
3008964fefecSStefano Zampini 
3009964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3010964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
301151694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
301251694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
301351694757SStefano Zampini     if (nullsp) {
301451694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
301551694757SStefano Zampini     }
301612edc857SStefano Zampini     if (applytranspose) {
3017964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
301812edc857SStefano Zampini     } else {
3019964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
302012edc857SStefano Zampini     }
302151694757SStefano Zampini     if (nullsp) {
302251694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
302351694757SStefano Zampini     }
302412edc857SStefano Zampini   }
3025674ae819SStefano Zampini 
3026674ae819SStefano Zampini   /* Local solution on R nodes */
302780677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
302880677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
30299f00e9b4SStefano Zampini   }
3030674ae819SStefano Zampini 
30319f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
30329f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
303312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3034674ae819SStefano Zampini 
3035674ae819SStefano Zampini   /* Sum contributions from two levels */
3036dc359a40SStefano Zampini   if (applytranspose) {
3037dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3038dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3039dc359a40SStefano Zampini   } else {
3040674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
30418eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3042dc359a40SStefano Zampini   }
3043efc2fbd9SStefano Zampini   /* store p0 */
30444f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
3045efc2fbd9SStefano Zampini     PetscScalar *array;
30464f1b2e48SStefano Zampini     PetscInt    j;
3047efc2fbd9SStefano Zampini 
3048efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
30494f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3050efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3051efc2fbd9SStefano Zampini   }
3052674ae819SStefano Zampini   PetscFunctionReturn(0);
3053674ae819SStefano Zampini }
3054674ae819SStefano Zampini 
3055674ae819SStefano Zampini #undef __FUNCT__
3056674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
305712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3058674ae819SStefano Zampini {
3059674ae819SStefano Zampini   PetscErrorCode ierr;
3060674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
306158da7f69SStefano Zampini   PetscScalar    *array;
306212edc857SStefano Zampini   Vec            from,to;
3063674ae819SStefano Zampini 
3064674ae819SStefano Zampini   PetscFunctionBegin;
306512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
306612edc857SStefano Zampini     from = pcbddc->coarse_vec;
306712edc857SStefano Zampini     to = pcbddc->vec1_P;
306812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
306912edc857SStefano Zampini       Vec tvec;
307058da7f69SStefano Zampini 
307158da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
307258da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
307312edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
307458da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
307558da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
307658da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
307712edc857SStefano Zampini     }
307812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
307912edc857SStefano Zampini     from = pcbddc->vec1_P;
308012edc857SStefano Zampini     to = pcbddc->coarse_vec;
308112edc857SStefano Zampini   }
308212edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3083674ae819SStefano Zampini   PetscFunctionReturn(0);
3084674ae819SStefano Zampini }
3085674ae819SStefano Zampini 
3086674ae819SStefano Zampini #undef __FUNCT__
3087674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
308812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3089674ae819SStefano Zampini {
3090674ae819SStefano Zampini   PetscErrorCode ierr;
3091674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
309258da7f69SStefano Zampini   PetscScalar    *array;
309312edc857SStefano Zampini   Vec            from,to;
3094674ae819SStefano Zampini 
3095674ae819SStefano Zampini   PetscFunctionBegin;
309612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
309712edc857SStefano Zampini     from = pcbddc->coarse_vec;
309812edc857SStefano Zampini     to = pcbddc->vec1_P;
309912edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
310012edc857SStefano Zampini     from = pcbddc->vec1_P;
310112edc857SStefano Zampini     to = pcbddc->coarse_vec;
310212edc857SStefano Zampini   }
310312edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
310412edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
310512edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
310612edc857SStefano Zampini       Vec tvec;
310758da7f69SStefano Zampini 
310812edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
310958da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
311058da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
311158da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
311258da7f69SStefano Zampini     }
311358da7f69SStefano Zampini   } else {
311458da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
311558da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
311612edc857SStefano Zampini     }
311712edc857SStefano Zampini   }
3118674ae819SStefano Zampini   PetscFunctionReturn(0);
3119674ae819SStefano Zampini }
3120674ae819SStefano Zampini 
3121984c4197SStefano Zampini /* uncomment for testing purposes */
3122984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3123674ae819SStefano Zampini #undef __FUNCT__
3124674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3125674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3126674ae819SStefano Zampini {
3127674ae819SStefano Zampini   PetscErrorCode    ierr;
3128674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3129674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3130674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3131984c4197SStefano Zampini   /* one and zero */
3132984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3133984c4197SStefano Zampini   /* space to store constraints and their local indices */
31349162d606SStefano Zampini   PetscScalar       *constraints_data;
31359162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
31369162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
31379162d606SStefano Zampini   PetscInt          *constraints_n;
3138984c4197SStefano Zampini   /* iterators */
3139b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3140984c4197SStefano Zampini   /* BLAS integers */
3141e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3142e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3143c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3144727cdba6SStefano Zampini   /* reuse */
31450e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
31460e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3147984c4197SStefano Zampini   /* change of basis */
3148b3d85658SStefano Zampini   PetscBool         qr_needed;
31499162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3150984c4197SStefano Zampini   /* auxiliary stuff */
315164efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
31528a0068c3SStefano Zampini   PetscInt          ncc;
3153984c4197SStefano Zampini   /* some quantities */
315445a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3155a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3156984c4197SStefano Zampini 
3157674ae819SStefano Zampini   PetscFunctionBegin;
31588e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
31598e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
31608e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3161088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3162088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
31630e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
31640e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
31650e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
31660e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
31670e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3168088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3169cf5a6209SStefano Zampini 
3170cf5a6209SStefano Zampini   /* print some info */
3171cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
3172cf5a6209SStefano Zampini     IS       vertices;
3173cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
3174cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
3175cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
3176cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
31771575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3178cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3179cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3180fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
3181fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
3182cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
31831575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3184cf5a6209SStefano Zampini   }
3185cf5a6209SStefano Zampini 
3186cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
31879162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3188cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3189cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3190cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3191cf5a6209SStefano Zampini     PetscScalar  *array;
3192cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3193cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3194674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3195b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3196674ae819SStefano Zampini     PetscScalar  *work;
3197674ae819SStefano Zampini     PetscReal    *singular_vals;
3198674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3199674ae819SStefano Zampini     PetscReal    *rwork;
3200674ae819SStefano Zampini #endif
3201674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3202674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3203674ae819SStefano Zampini #else
3204964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3205964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3206674ae819SStefano Zampini #endif
3207674ae819SStefano Zampini 
3208674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3209d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3210d06fc5fdSStefano Zampini     /* free unneeded index sets */
3211d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3212d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3213674ae819SStefano Zampini     }
3214d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3215d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3216d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3217d06fc5fdSStefano Zampini       }
3218d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3219d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3220d06fc5fdSStefano Zampini     }
3221d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3222d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3223d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3224d06fc5fdSStefano Zampini       }
3225d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3226d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3227d06fc5fdSStefano Zampini     }
322870022509SStefano Zampini 
322970022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
323070022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
323170022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
323270022509SStefano Zampini     if (pcbddc->NullSpace) {
323370022509SStefano Zampini       PetscBool tbool[2],gbool[2];
323470022509SStefano Zampini 
323570022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
3236b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
3237d06fc5fdSStefano Zampini         if (!ISForEdges) {
3238d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
3239d06fc5fdSStefano Zampini         }
3240b8ffe317SStefano Zampini       }
3241d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
3242d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
3243d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3244d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
3245d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
324698a51de6SStefano Zampini     }
324770022509SStefano Zampini #endif
324808122e43SStefano Zampini 
3249674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3250674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3251674ae819SStefano Zampini     if (nearnullsp) {
3252674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3253f4ddd8eeSStefano Zampini       /* remove any stored info */
3254f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3255f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3256f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3257f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3258f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3259473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3260f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3261f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3262f4ddd8eeSStefano Zampini       }
3263984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3264984c4197SStefano Zampini       nnsp_size = 0;
3265674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3266674ae819SStefano Zampini     }
3267984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3268984c4197SStefano Zampini     max_constraints = nnsp_size;
3269984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3270984c4197SStefano Zampini 
3271674ae819SStefano Zampini     /*
3272674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
32739162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
32749162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
32759162d606SStefano Zampini          There can be multiple constraints per connected component
3276674ae819SStefano Zampini                                                                                                                                                            */
3277674ae819SStefano Zampini     n_vertices = 0;
3278674ae819SStefano Zampini     if (ISForVertices) {
3279674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3280674ae819SStefano Zampini     }
32819162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
32829162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
32839162d606SStefano Zampini 
32849162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
32859162d606SStefano Zampini     total_counts *= max_constraints;
3286674ae819SStefano Zampini     total_counts += n_vertices;
32874641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
32889162d606SStefano Zampini 
3289674ae819SStefano Zampini     total_counts = 0;
3290674ae819SStefano Zampini     max_size_of_constraint = 0;
3291674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
32929162d606SStefano Zampini       IS used_is;
3293674ae819SStefano Zampini       if (i<n_ISForEdges) {
32949162d606SStefano Zampini         used_is = ISForEdges[i];
3295674ae819SStefano Zampini       } else {
32969162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3297674ae819SStefano Zampini       }
32989162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3299674ae819SStefano Zampini       total_counts += j;
3300674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3301674ae819SStefano Zampini     }
33029162d606SStefano 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);
33039162d606SStefano Zampini 
3304984c4197SStefano Zampini     /* get local part of global near null space vectors */
3305785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3306984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3307984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3308e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3309e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3310984c4197SStefano Zampini     }
3311674ae819SStefano Zampini 
3312242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3313242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3314a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3315242a89d7SStefano Zampini 
3316984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3317a773dcb8SStefano Zampini     if (!skip_lapack) {
3318674ae819SStefano Zampini       PetscScalar temp_work;
3319911cabfeSStefano Zampini 
3320674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3321984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3322785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3323785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3324785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3325674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3326785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3327674ae819SStefano Zampini #endif
3328674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3329c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3330c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3331674ae819SStefano Zampini       lwork = -1;
3332674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3333674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3334c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3335674ae819SStefano Zampini #else
3336c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3337674ae819SStefano Zampini #endif
3338674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3339984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3340674ae819SStefano Zampini #else /* on missing GESVD */
3341674ae819SStefano Zampini       /* SVD */
3342674ae819SStefano Zampini       PetscInt max_n,min_n;
3343674ae819SStefano Zampini       max_n = max_size_of_constraint;
3344984c4197SStefano Zampini       min_n = max_constraints;
3345984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3346674ae819SStefano Zampini         min_n = max_size_of_constraint;
3347984c4197SStefano Zampini         max_n = max_constraints;
3348674ae819SStefano Zampini       }
3349785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3350674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3351785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3352674ae819SStefano Zampini #endif
3353674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3354674ae819SStefano Zampini       lwork = -1;
3355e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3356e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3357b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3358674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3359674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
33609162d606SStefano 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));
3361674ae819SStefano Zampini #else
33629162d606SStefano 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));
3363674ae819SStefano Zampini #endif
3364674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3365984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3366984c4197SStefano Zampini #endif /* on missing GESVD */
3367674ae819SStefano Zampini       /* Allocate optimal workspace */
3368674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3369854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3370674ae819SStefano Zampini     }
3371674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3372674ae819SStefano Zampini     total_counts = 0;
33739162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
33749162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3375674ae819SStefano Zampini     /* vertices */
33769162d606SStefano Zampini     if (n_vertices) {
3377674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
33789162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3379674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
33809162d606SStefano Zampini         constraints_n[total_counts] = 1;
33819162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
33829162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
33839162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3384674ae819SStefano Zampini         total_counts++;
3385674ae819SStefano Zampini       }
3386674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3387674ae819SStefano Zampini       n_vertices = total_counts;
3388674ae819SStefano Zampini     }
3389984c4197SStefano Zampini 
3390674ae819SStefano Zampini     /* edges and faces */
33919162d606SStefano Zampini     total_counts_cc = total_counts;
3392911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
33939162d606SStefano Zampini       IS        used_is;
33949162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
33959162d606SStefano Zampini 
3396911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
33979162d606SStefano Zampini         used_is = ISForEdges[ncc];
3398984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3399674ae819SStefano Zampini       } else {
34009162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3401984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3402674ae819SStefano Zampini       }
3403674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
34049162d606SStefano Zampini 
34059162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
34069162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3407984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3408984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3409674ae819SStefano Zampini       if (nnsp_has_cnst) {
34105b08dc53SStefano Zampini         PetscScalar quad_value;
34119162d606SStefano Zampini 
34129162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
34139162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
34149162d606SStefano Zampini 
3415a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3416674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3417a773dcb8SStefano Zampini         } else {
3418a773dcb8SStefano Zampini           quad_value = 1.0;
3419a773dcb8SStefano Zampini         }
3420674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
34219162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3422674ae819SStefano Zampini         }
34239162d606SStefano Zampini         temp_constraints++;
3424674ae819SStefano Zampini         total_counts++;
3425674ae819SStefano Zampini       }
3426674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3427984c4197SStefano Zampini         PetscReal real_value;
34289162d606SStefano Zampini         PetscScalar *ptr_to_data;
34299162d606SStefano Zampini 
3430984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
34319162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3432674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
34339162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3434674ae819SStefano Zampini         }
3435984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3436984c4197SStefano Zampini         /* check if array is null on the connected component */
3437e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
34389162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
34395b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3440674ae819SStefano Zampini           temp_constraints++;
3441674ae819SStefano Zampini           total_counts++;
34429162d606SStefano Zampini           if (!idxs_copied) {
34439162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
34449162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3445674ae819SStefano Zampini           }
3446674ae819SStefano Zampini         }
34479162d606SStefano Zampini       }
34489162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
344945a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3450eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3451a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
34529162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
34539162d606SStefano Zampini 
34549162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3455a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
34569162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3457a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
34589162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3459a773dcb8SStefano Zampini         } else { /* perform SVD */
3460984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
34619162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3462674ae819SStefano Zampini 
3463674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3464984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3465984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3466984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3467984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3468984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3469984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3470984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3471984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3472674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3473e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3474984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3475674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3476674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
34779162d606SStefano 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));
3478674ae819SStefano Zampini             }
3479674ae819SStefano Zampini           }
3480e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3481e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3482e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3483674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3484c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3485674ae819SStefano Zampini #else
3486c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3487674ae819SStefano Zampini #endif
3488674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3489984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3490984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3491674ae819SStefano Zampini           j = 0;
3492984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3493674ae819SStefano Zampini           total_counts = total_counts-j;
349445a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3495e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3496c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3497c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3498c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3499c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3500c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3501c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3502674ae819SStefano Zampini           if (j<temp_constraints) {
3503984c4197SStefano Zampini             PetscInt ii;
3504984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3505674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
35069162d606SStefano 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));
3507674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3508984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3509674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
35109162d606SStefano 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];
3511674ae819SStefano Zampini               }
3512674ae819SStefano Zampini             }
3513674ae819SStefano Zampini           }
3514674ae819SStefano Zampini #else  /* on missing GESVD */
3515e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3516e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3517b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3518674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3519674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
35209162d606SStefano 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));
3521674ae819SStefano Zampini #else
35229162d606SStefano 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));
3523674ae819SStefano Zampini #endif
3524984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3525674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3526984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3527e310c8b4SStefano Zampini           k = temp_constraints;
3528e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3529674ae819SStefano Zampini           j = 0;
3530e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
353145a1bb75SStefano Zampini           valid_constraints = k-j;
3532911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3533984c4197SStefano Zampini #endif /* on missing GESVD */
3534674ae819SStefano Zampini         }
3535a773dcb8SStefano Zampini       }
35369162d606SStefano Zampini       /* update pointers information */
35379162d606SStefano Zampini       if (valid_constraints) {
35389162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
35399162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
35409162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
35419162d606SStefano Zampini         /* set change_of_basis flag */
354245a1bb75SStefano Zampini         if (boolforchange) {
3543b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
35449162d606SStefano Zampini         }
3545b3d85658SStefano Zampini         total_counts_cc++;
354645a1bb75SStefano Zampini       }
354745a1bb75SStefano Zampini     }
3548984c4197SStefano Zampini     /* free workspace */
35498f1c130eSStefano Zampini     if (!skip_lapack) {
3550984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3551984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3552984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3553984c4197SStefano Zampini #endif
3554984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3555984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3556984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3557984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3558984c4197SStefano Zampini #endif
3559984c4197SStefano Zampini     }
3560984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3561984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3562984c4197SStefano Zampini     }
3563984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3564cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3565cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3566cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3567cf5a6209SStefano Zampini     }
3568cf5a6209SStefano Zampini     if (n_ISForFaces) {
3569cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3570cf5a6209SStefano Zampini     }
3571cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3572cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3573cf5a6209SStefano Zampini     }
3574cf5a6209SStefano Zampini     if (n_ISForEdges) {
3575cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3576cf5a6209SStefano Zampini     }
3577cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
357808122e43SStefano Zampini   } else {
357908122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3580984c4197SStefano Zampini 
358108122e43SStefano Zampini     total_counts = 0;
358208122e43SStefano Zampini     n_vertices = 0;
3583d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3584d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
358508122e43SStefano Zampini     }
358608122e43SStefano Zampini     max_constraints = 0;
35879162d606SStefano Zampini     total_counts_cc = 0;
358808122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
358908122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
35909162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
359108122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
359208122e43SStefano Zampini     }
35939162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
35949162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
35959162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
35969162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
359774d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
35989162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
35999162d606SStefano Zampini     total_counts_cc = 0;
36009162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
36019162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
36029162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
360308122e43SStefano Zampini       }
360408122e43SStefano Zampini     }
36059162d606SStefano Zampini #if 0
36069162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
36079162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
36089162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
36099162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
36109162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
36119162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
36129162d606SStefano Zampini       }
36139162d606SStefano Zampini       printf("\n");
36149162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
36159162d606SStefano Zampini     }
36161b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
36178bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
36181b968477SStefano Zampini     }
36191b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
36208bec7fa6SStefano 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]);
36211b968477SStefano Zampini     }
362208122e43SStefano Zampini #endif
362308122e43SStefano Zampini 
36248bec7fa6SStefano Zampini     max_size_of_constraint = 0;
36259162d606SStefano 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]);
36269162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
362708122e43SStefano Zampini     /* Change of basis */
3628b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
362908122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
363008122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
363108122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3632b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
363308122e43SStefano Zampini         }
363408122e43SStefano Zampini       }
363508122e43SStefano Zampini     }
363608122e43SStefano Zampini   }
3637984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
36384f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
363908122e43SStefano Zampini 
36409162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
36419162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
36429162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
36439162d606SStefano 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);
364408122e43SStefano Zampini   }
3645674ae819SStefano Zampini 
3646674ae819SStefano Zampini   /* Create constraint matrix */
3647674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
364816f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
3649984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
3650984c4197SStefano Zampini 
3651984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
3652a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
3653a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
365474d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
3655984c4197SStefano Zampini   total_primal_vertices=0;
3656b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
36579162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
36589162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3659984c4197SStefano Zampini     if (size_of_constraint == 1) {
36609162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
3661b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
366264efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
36639162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
36649162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
3665a717540cSStefano Zampini       }
3666b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
366774d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
3668a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
3669a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
3670a717540cSStefano Zampini       }
3671fa434743SStefano Zampini     } else {
3672b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
3673fa434743SStefano Zampini     }
3674a717540cSStefano Zampini   }
3675b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
3676b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
3677674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
367870022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3679b3d85658SStefano Zampini 
36804f1b2e48SStefano 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);
36810e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
36820e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
3683984c4197SStefano Zampini 
3684984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
368574d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
3686785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
3687984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
368874d5cdf7SStefano Zampini 
3689984c4197SStefano Zampini   j = total_primal_vertices;
369074d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
3691b3d85658SStefano Zampini   cum = total_primal_vertices;
36929162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
36934641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
3694b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
3695b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
3696b3d85658SStefano Zampini       cum++;
36979162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
369874d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
369974d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
370074d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
370174d5cdf7SStefano Zampini       }
37029162d606SStefano Zampini       j += constraints_n[i];
3703674ae819SStefano Zampini     }
3704674ae819SStefano Zampini   }
3705674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
3706674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
3707088faed8SStefano Zampini 
3708674ae819SStefano Zampini   /* set values in constraint matrix */
3709984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
37100e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3711674ae819SStefano Zampini   }
3712984c4197SStefano Zampini   total_counts = total_primal_vertices;
37139162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
37144641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
37159162d606SStefano Zampini       PetscInt *cols;
37169162d606SStefano Zampini 
37179162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
37189162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
37199162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
37209162d606SStefano Zampini         PetscInt    row = total_counts+k;
37219162d606SStefano Zampini         PetscScalar *vals;
37229162d606SStefano Zampini 
37239162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
37249162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
37259162d606SStefano Zampini       }
37269162d606SStefano Zampini       total_counts += constraints_n[i];
3727674ae819SStefano Zampini     }
3728674ae819SStefano Zampini   }
3729674ae819SStefano Zampini   /* assembling */
3730674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3731674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3732088faed8SStefano Zampini 
3733984c4197SStefano Zampini   /*
373445a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3735984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
3736984c4197SStefano Zampini   */
3737674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
3738674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
3739026de310SStefano Zampini     /* dual and primal dofs on a single cc */
3740984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
3741984c4197SStefano Zampini     /* working stuff for GEQRF */
374281d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
3743984c4197SStefano Zampini     PetscBLASInt lqr_work;
3744984c4197SStefano Zampini     /* working stuff for UNGQR */
3745984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
3746984c4197SStefano Zampini     PetscBLASInt lgqr_work;
3747984c4197SStefano Zampini     /* working stuff for TRTRS */
3748984c4197SStefano Zampini     PetscScalar  *trs_rhs;
37493f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
3750984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
3751984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
3752984c4197SStefano Zampini     PetscScalar  *start_vals;
3753984c4197SStefano Zampini     /* working stuff for values insertion */
37544641a718SStefano Zampini     PetscBT      is_primal;
375564efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
3756906d46d4SStefano Zampini     /* matrix sizes */
3757906d46d4SStefano Zampini     PetscInt     global_size,local_size;
3758906d46d4SStefano Zampini     /* temporary change of basis */
3759906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
3760cf5a6209SStefano Zampini     /* extra space for debugging */
3761cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
3762984c4197SStefano Zampini 
3763906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
3764906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
376516f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
3766bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3767906d46d4SStefano Zampini     /* nonzeros for local mat */
3768bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
3769bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
37709162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
3771a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
37729162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3773a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
37749162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
3775a717540cSStefano Zampini         } else {
37769162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
37779162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
3778a717540cSStefano Zampini         }
3779a717540cSStefano Zampini       }
3780a717540cSStefano Zampini     }
3781906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
3782bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3783a717540cSStefano Zampini     /* Set initial identity in the matrix */
3784bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
3785906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3786a717540cSStefano Zampini     }
3787a717540cSStefano Zampini 
3788a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
3789a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3790a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3791a717540cSStefano Zampini     }
3792a717540cSStefano Zampini 
3793a717540cSStefano Zampini 
3794a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
3795a717540cSStefano Zampini     /*
3796a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3797a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3798a717540cSStefano Zampini 
3799a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
3800a717540cSStefano Zampini 
3801a6b551f4SStefano 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)
3802a6b551f4SStefano Zampini 
3803a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
3804a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
3805a717540cSStefano Zampini             |              ...                        |
3806a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
3807a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3808a717540cSStefano Zampini 
3809a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
3810a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3811a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3812a6b551f4SStefano Zampini 
3813a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
3814a717540cSStefano Zampini     */
3815a717540cSStefano Zampini     if (qr_needed) {
3816984c4197SStefano Zampini       /* space to store Q */
3817854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3818984c4197SStefano Zampini       /* first we issue queries for optimal work */
38193f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
38203f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
38213f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3822984c4197SStefano Zampini       lqr_work = -1;
38233f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3824984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3825984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3826785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3827984c4197SStefano Zampini       lgqr_work = -1;
38283f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
38293f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
38303f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
38313f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
38323f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
38333f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3834984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3835984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3836785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3837984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3838785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3839984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3840785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3841a717540cSStefano Zampini       /* allocating workspace for check */
3842a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3843cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3844a717540cSStefano Zampini       }
3845a717540cSStefano Zampini     }
3846984c4197SStefano Zampini     /* array to store whether a node is primal or not */
38474641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3848473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
38490e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
385039e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
385139e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
38524641a718SStefano Zampini     }
385339e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
385439e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
385539e2fb2aSStefano Zampini     }
385639e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3857984c4197SStefano Zampini 
3858a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
38599162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
38609162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
38614641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3862984c4197SStefano Zampini         /* get constraint info */
38639162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3864984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3865984c4197SStefano Zampini 
3866984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
38679162d606SStefano 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);
3868674ae819SStefano Zampini         }
3869984c4197SStefano Zampini 
3870fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3871a717540cSStefano Zampini 
3872a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3873a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
38749162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3875a717540cSStefano Zampini           }
3876984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
38779162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3878984c4197SStefano Zampini 
3879984c4197SStefano Zampini           /* compute QR decomposition of constraints */
38803f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
38813f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
38823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3883674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38843f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3885984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3886674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3887984c4197SStefano Zampini 
3888984c4197SStefano Zampini           /* explictly compute R^-T */
3889984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3890984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
38913f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
38923f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
38933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
38943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3895984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38963f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3897984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3898984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3899984c4197SStefano Zampini 
3900a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
39013f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
39023f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39033f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
39043f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3905984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
39063f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3907984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3908984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3909984c4197SStefano Zampini 
3910984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3911984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3912984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
39133f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
39143f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
39153f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
39163f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
39173f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
39183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3919984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
39209162d606SStefano 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));
3921984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
39229162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3923984c4197SStefano Zampini 
3924984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
39259162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3926984c4197SStefano Zampini           /* insert cols for primal dofs */
3927984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3928984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
39299162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3930906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3931984c4197SStefano Zampini           }
3932984c4197SStefano Zampini           /* insert cols for dual dofs */
3933984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
39349162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3935984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
39369162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3937906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3938984c4197SStefano Zampini               j++;
3939674ae819SStefano Zampini             }
3940674ae819SStefano Zampini           }
3941984c4197SStefano Zampini 
3942984c4197SStefano Zampini           /* check change of basis */
3943984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3944984c4197SStefano Zampini             PetscInt   ii,jj;
3945984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3946c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3947c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3948c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3949c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3950c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3951c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3952984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3953cf5a6209SStefano 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));
3954984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3955984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3956984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3957cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3958cf5a6209SStefano 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;
3959674ae819SStefano Zampini               }
3960674ae819SStefano Zampini             }
3961984c4197SStefano Zampini             if (!valid_qr) {
396222d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3963984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3964984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3965cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3966cf5a6209SStefano 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]));
3967674ae819SStefano Zampini                   }
3968cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3969cf5a6209SStefano 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]));
3970984c4197SStefano Zampini                   }
3971984c4197SStefano Zampini                 }
3972984c4197SStefano Zampini               }
3973674ae819SStefano Zampini             } else {
397422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3975674ae819SStefano Zampini             }
3976674ae819SStefano Zampini           }
3977a717540cSStefano Zampini         } else { /* simple transformation block */
3978a717540cSStefano Zampini           PetscInt    row,col;
3979a6b551f4SStefano Zampini           PetscScalar val,norm;
3980a6b551f4SStefano Zampini 
3981a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39829162d606SStefano 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));
3983a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
39849162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
39859162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3986bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
39879162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3988906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
39899162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3990a717540cSStefano Zampini             } else {
3991a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
39929162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3993a717540cSStefano Zampini                 if (row != col) {
39949162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3995a717540cSStefano Zampini                 } else {
39969162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3997a717540cSStefano Zampini                 }
3998906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3999a717540cSStefano Zampini               }
4000a717540cSStefano Zampini             }
4001a717540cSStefano Zampini           }
400298a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
400322d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4004a717540cSStefano Zampini           }
4005674ae819SStefano Zampini         }
4006984c4197SStefano Zampini       } else {
4007984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
40089162d606SStefano 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);
4009674ae819SStefano Zampini         }
4010674ae819SStefano Zampini       }
4011674ae819SStefano Zampini     }
4012a717540cSStefano Zampini 
4013a717540cSStefano Zampini     /* free workspace */
4014a717540cSStefano Zampini     if (qr_needed) {
4015984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4016cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4017984c4197SStefano Zampini       }
4018984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4019984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4020984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4021984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4022984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4023674ae819SStefano Zampini     }
4024a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4025906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4026906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4027906d46d4SStefano Zampini 
4028906d46d4SStefano Zampini     /* assembling of global change of variable */
4029bbb9e6c6SStefano Zampini     {
4030bbb9e6c6SStefano Zampini       Mat      tmat;
403116f15bc4SStefano Zampini       PetscInt bs;
403216f15bc4SStefano Zampini 
4033906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4034906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4035bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4036bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4037bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4038bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
403916f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
404016f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4041906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4042bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4043bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4044bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4045bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4046bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4047e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4048e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4049bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4050bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
4051906d46d4SStefano Zampini     }
4052906d46d4SStefano Zampini     /* check */
4053906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
4054906d46d4SStefano Zampini       PetscReal error;
4055906d46d4SStefano Zampini       Vec       x,x_change;
4056906d46d4SStefano Zampini 
4057906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4058906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4059906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4060906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4061e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4062e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4063bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4064e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4065e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4066906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4067906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4068906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4069906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4070bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4071906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
4072906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4073906d46d4SStefano Zampini     }
4074b96c3477SStefano Zampini 
4075b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
4076b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
4077b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4078b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
4079ac632422SStefano Zampini         Mat                    S_new,tmat;
4080b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
4081b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
4082b087196eSStefano Zampini         const PetscScalar      *array;
4083b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
4084b087196eSStefano Zampini         PetscInt               i,n_V;
4085bbb9e6c6SStefano Zampini 
4086bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
40876816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4088b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4089b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4090b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4091b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4092bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4093b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4094ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4095b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4096ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4097b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4098b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4099b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4100b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4101b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4102b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
4103b087196eSStefano Zampini           PetscScalar val;
4104b087196eSStefano Zampini           PetscInt    idx;
4105b087196eSStefano Zampini 
4106b087196eSStefano Zampini           idx = idxs_V[i];
4107b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
4108b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4109b087196eSStefano Zampini         }
4110b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4111b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4112ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
4113ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4114ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
4115ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4116b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4117ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4118b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4119ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
4120ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4121ac632422SStefano Zampini         }
4122b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4123b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4124b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4125b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4126b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
4127b96c3477SStefano Zampini       }
4128b96c3477SStefano Zampini     }
4129906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
4130906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
4131b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4132b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4133b9b85e73SStefano Zampini   }
4134906d46d4SStefano Zampini 
4135906d46d4SStefano Zampini   /* set up change of basis context */
4136906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
4137906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
4138906d46d4SStefano Zampini 
4139906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
4140906d46d4SStefano Zampini       PetscInt global_size,local_size;
4141906d46d4SStefano Zampini 
4142906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4143906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4144906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
4145906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4146906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
4147906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
4148906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
4149906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
4150906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
4151906d46d4SStefano Zampini     } else {
4152906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
4153906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
4154906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
4155906d46d4SStefano Zampini     }
4156906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
4157906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4158906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
4159906d46d4SStefano Zampini     } else {
4160906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4161906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
4162906d46d4SStefano Zampini     }
4163906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
4164906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
4165906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4166906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4167a8661815SStefano Zampini   } else {
4168a8661815SStefano Zampini     ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr);
4169b9b85e73SStefano Zampini   }
4170a717540cSStefano Zampini 
41714f1b2e48SStefano Zampini   /* add pressure dofs to set of primal nodes for numbering purposes */
41724f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
41734f1b2e48SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
41744f1b2e48SStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4175019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4176019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
4177019a44ceSStefano Zampini     pcbddc->local_primal_size++;
4178019a44ceSStefano Zampini   }
4179019a44ceSStefano Zampini 
4180019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
4181727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
4182727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
41839f47a83aSStefano 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);
4184c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
41850e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
41869f47a83aSStefano 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);
4187727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4188727cdba6SStefano Zampini     }
41890e6343abSStefano Zampini   }
41900e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4191727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4192727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4193727cdba6SStefano Zampini 
4194a717540cSStefano Zampini   /* flush dbg viewer */
4195b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4196b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4197b8ffe317SStefano Zampini   }
4198a717540cSStefano Zampini 
4199e310c8b4SStefano Zampini   /* free workspace */
4200a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
42014641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
420208122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
42039162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
42049162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
420508122e43SStefano Zampini   } else {
42069162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
42079162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
42089162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
420908122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
421008122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
42119162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
42129162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
421308122e43SStefano Zampini   }
4214674ae819SStefano Zampini   PetscFunctionReturn(0);
4215674ae819SStefano Zampini }
4216674ae819SStefano Zampini 
4217674ae819SStefano Zampini #undef __FUNCT__
4218674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4219674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4220674ae819SStefano Zampini {
4221674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4222674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4223674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
42247fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
4225674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
4226674ae819SStefano Zampini 
4227674ae819SStefano Zampini   PetscFunctionBegin;
42288e61c736SStefano Zampini   /* Reset previously computed graph */
42298e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4230674ae819SStefano Zampini   /* Init local Graph struct */
42317fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
42323bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4233674ae819SStefano Zampini 
4234575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
42355099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
42365099eff2SStefano 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);
4237575ad6abSStefano Zampini   }
42389577ea80SStefano Zampini 
4239674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4240*d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
42414d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
42424d379d7bSStefano Zampini     PetscInt  nvtxs;
4243e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4244674ae819SStefano Zampini 
42452fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
42462fffb893SStefano Zampini     if (flg_row) {
42474d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4248b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
42492fffb893SStefano Zampini     }
42502fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4251674ae819SStefano Zampini   }
42529b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
42539b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4254674ae819SStefano Zampini   }
4255674ae819SStefano Zampini 
425663602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
4257674ae819SStefano Zampini   vertex_size = 1;
425863602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
425963602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
426095ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
426163602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
4262e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
426363602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
4264674ae819SStefano Zampini       }
426563602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
426663602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
426763602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
4268674ae819SStefano Zampini     }
426963602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
4270674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
427163602bcaSStefano Zampini   } else {
427263602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
427363602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
4274854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
427563602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
427663602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
427763602bcaSStefano Zampini       }
427863602bcaSStefano Zampini     }
4279674ae819SStefano Zampini   }
4280674ae819SStefano Zampini 
4281674ae819SStefano Zampini   /* Setup of Graph */
4282785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
4283e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
4284785d1243SStefano Zampini   }
4285785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
4286e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
4287785d1243SStefano Zampini   }
428830368db7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) { /* need to convert from global to local */
428930368db7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
429030368db7SStefano Zampini   }
429130368db7SStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
4292674ae819SStefano Zampini 
42934f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
42944f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
42954f1b2e48SStefano Zampini     PetscInt *local_subs;
42964f1b2e48SStefano Zampini 
42974f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
42984f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
42994f1b2e48SStefano Zampini       const PetscInt *idxs;
43004f1b2e48SStefano Zampini       PetscInt       nl,j;
43014f1b2e48SStefano Zampini 
43024f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
43034f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
43044f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
43054f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
43064f1b2e48SStefano Zampini       }
43074f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
43084f1b2e48SStefano Zampini     }
43094f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
43104f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
43114f1b2e48SStefano Zampini   }
43124f1b2e48SStefano Zampini 
4313674ae819SStefano Zampini   /* Graph's connected components analysis */
4314674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4315674ae819SStefano Zampini 
4316674ae819SStefano Zampini   /* print some info to stdout */
4317674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
4318302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
4319674ae819SStefano Zampini   }
4320fb180af4SStefano Zampini 
4321fb180af4SStefano Zampini   /* mark topography has done */
4322fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
4323674ae819SStefano Zampini   PetscFunctionReturn(0);
4324674ae819SStefano Zampini }
4325674ae819SStefano Zampini 
4326dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4327674ae819SStefano Zampini #undef __FUNCT__
4328674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4329dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4330674ae819SStefano Zampini {
4331dc456d91SStefano Zampini   PetscSF        sf;
4332dc456d91SStefano Zampini   PetscLayout    map;
4333dc456d91SStefano Zampini   const PetscInt *idxs;
4334dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4335dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4336dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4337dc456d91SStefano Zampini   PetscMPIInt    commsize;
4338674ae819SStefano Zampini   PetscBool      first_found;
4339674ae819SStefano Zampini   PetscErrorCode ierr;
4340674ae819SStefano Zampini 
4341674ae819SStefano Zampini   PetscFunctionBegin;
4342dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4343dc456d91SStefano Zampini   if (subset_mult) {
4344dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4345dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4346dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4347674ae819SStefano Zampini   }
4348dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4349dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4350dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4351dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4352dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4353dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4354674ae819SStefano Zampini   }
4355dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4356dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4357dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4358dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4359dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4360dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4361dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4362dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4363dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4364dc456d91SStefano Zampini 
4365dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4366dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4367dc456d91SStefano Zampini   if (subset_mult) {
4368dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4369dc456d91SStefano Zampini 
4370dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4371dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4372dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4373674ae819SStefano Zampini   } else {
4374dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4375674ae819SStefano Zampini   }
4376dc456d91SStefano Zampini   /* local size of new subset */
4377dc456d91SStefano Zampini   n_n = 0;
4378dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4379dc456d91SStefano Zampini 
4380dc456d91SStefano Zampini   /* global indexes in layout */
4381dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4382dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4383dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4384dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4385dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4386dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4387dc456d91SStefano Zampini 
4388dc456d91SStefano Zampini   /* reduce from leaves to roots */
4389dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
439064a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
439164a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4392dc456d91SStefano Zampini 
4393dc456d91SStefano Zampini   /* count indexes in local part of layout */
4394674ae819SStefano Zampini   nlocals = 0;
4395674ae819SStefano Zampini   first_index = -1;
4396674ae819SStefano Zampini   first_found = PETSC_FALSE;
4397dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4398dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4399674ae819SStefano Zampini       first_found = PETSC_TRUE;
4400674ae819SStefano Zampini       first_index = i;
4401674ae819SStefano Zampini     }
4402dc456d91SStefano Zampini     nlocals += root_data[i];
4403674ae819SStefano Zampini   }
4404dc456d91SStefano Zampini 
4405dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
44065fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4407dc456d91SStefano Zampini   start = 0;
440864a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
44095fa240b1SStefano Zampini #else
441064a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
44115fa240b1SStefano Zampini   start = start-nlocals;
44125fa240b1SStefano Zampini #endif
44135fa240b1SStefano Zampini 
4414dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4415dc456d91SStefano Zampini     *N_n = start + nlocals;
4416dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4417dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4418674ae819SStefano Zampini   }
44195fa240b1SStefano Zampini 
44205fa240b1SStefano Zampini   /* adapt root data with cumulative */
4421674ae819SStefano Zampini   if (first_found) {
4422dc456d91SStefano Zampini     PetscInt old_index;
4423dc456d91SStefano Zampini 
4424dc456d91SStefano Zampini     root_data[first_index] += start;
4425674ae819SStefano Zampini     old_index = first_index;
4426dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4427dc456d91SStefano Zampini       if (root_data[i]) {
4428dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4429674ae819SStefano Zampini         old_index = i;
4430674ae819SStefano Zampini       }
4431674ae819SStefano Zampini     }
4432674ae819SStefano Zampini   }
4433dc456d91SStefano Zampini 
4434dc456d91SStefano Zampini   /* from roots to leaves */
4435dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4436dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4437dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4438dc456d91SStefano Zampini 
4439dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4440dc456d91SStefano Zampini   if (subset_mult) {
4441dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4442dc456d91SStefano Zampini     PetscInt        cum;
4443dc456d91SStefano Zampini 
4444dc456d91SStefano Zampini     cum = 0;
4445dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4446dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4447dc456d91SStefano Zampini       PetscInt j;
4448dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4449674ae819SStefano Zampini     }
4450dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4451674ae819SStefano Zampini   } else {
4452dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4453dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4454674ae819SStefano Zampini     }
4455674ae819SStefano Zampini   }
4456dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4457dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4458674ae819SStefano Zampini   PetscFunctionReturn(0);
4459674ae819SStefano Zampini }
44609a7d3425SStefano Zampini 
44619a7d3425SStefano Zampini #undef __FUNCT__
44629a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
44639a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
44649a7d3425SStefano Zampini {
44659a7d3425SStefano Zampini   PetscInt       i,j;
44669a7d3425SStefano Zampini   PetscScalar    *alphas;
44679a7d3425SStefano Zampini   PetscErrorCode ierr;
44689a7d3425SStefano Zampini 
44699a7d3425SStefano Zampini   PetscFunctionBegin;
44709a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4471785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
44729a7d3425SStefano Zampini   for (i=0;i<n;i++) {
44739a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
44749a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
44759a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
44769a7d3425SStefano Zampini   }
44779a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
44789a7d3425SStefano Zampini   PetscFunctionReturn(0);
44799a7d3425SStefano Zampini }
44809a7d3425SStefano Zampini 
4481e7931f94SStefano Zampini #undef __FUNCT__
448270cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
4483b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
4484e7931f94SStefano Zampini {
448552e5ac9dSStefano Zampini   IS             ranks_send_to;
4486e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4487e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
448852e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
448952e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
44903837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
44912b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
4492e7931f94SStefano Zampini   PetscSubcomm   subcomm;
449352e5ac9dSStefano Zampini   PetscErrorCode ierr;
4494a57a6d2fSStefano Zampini 
4495e7931f94SStefano Zampini   PetscFunctionBegin;
44962b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
44972b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
44982b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
4499e7931f94SStefano Zampini 
4500e7931f94SStefano Zampini   /* Get info on mapping */
45013bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
45023bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4503e7931f94SStefano Zampini 
4504e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4505785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4506e7931f94SStefano Zampini   xadj[0] = 0;
4507e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4508785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4509785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
4510e7931f94SStefano Zampini 
45112b510759SStefano Zampini   if (threshold) {
4512d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
45132b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
4514d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
4515d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4516d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4517d023bfaeSStefano Zampini         xadj_count++;
4518e7931f94SStefano Zampini       }
4519e7931f94SStefano Zampini     }
4520d023bfaeSStefano Zampini     xadj[1] = xadj_count;
4521c8587f34SStefano Zampini   } else {
4522e7931f94SStefano Zampini     if (xadj[1]) {
4523e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
4524e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
4525c8587f34SStefano Zampini     }
4526e7931f94SStefano Zampini   }
45273bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4528e7931f94SStefano Zampini   if (use_square) {
4529e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4530e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
4531e7931f94SStefano Zampini     }
4532e7931f94SStefano Zampini   }
4533e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4534e7931f94SStefano Zampini 
45353837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4536e7931f94SStefano Zampini 
4537e7931f94SStefano Zampini   /*
4538e7931f94SStefano Zampini     Restrict work on active processes only.
4539e7931f94SStefano Zampini   */
4540e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
4541e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
4542e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
45432b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
4544d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4545e7931f94SStefano Zampini   if (color) {
4546e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4547e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4548e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4549c8587f34SStefano Zampini   } else {
455052e5ac9dSStefano Zampini     Mat             subdomain_adj;
455152e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
455252e5ac9dSStefano Zampini     MatPartitioning partitioner;
455352e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
455452e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
4555b0c7d250SStefano Zampini     PetscBool       aggregate;
4556b0c7d250SStefano Zampini 
4557306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
4558785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
4559e7931f94SStefano Zampini     prank = rank;
4560306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
45618002ef2cSStefano Zampini     /*
4562e7931f94SStefano Zampini     for (i=0;i<size;i++) {
4563e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
4564c8587f34SStefano Zampini     }
45658002ef2cSStefano Zampini     */
4566e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4567e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4568c8587f34SStefano Zampini     }
4569e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4570b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
4571b0c7d250SStefano Zampini     if (aggregate) {
4572b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
4573b0c7d250SStefano Zampini       PetscMPIInt nrank;
4574b0c7d250SStefano Zampini       PetscScalar *vals;
4575b0c7d250SStefano Zampini 
4576b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
4577b0c7d250SStefano Zampini       lrows = 0;
4578b0c7d250SStefano Zampini       if (nrank<redprocs) {
4579b0c7d250SStefano Zampini         lrows = size/redprocs;
4580b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
4581b0c7d250SStefano Zampini       }
45825fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
4583b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
4584b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4585b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4586b0c7d250SStefano Zampini       row = nrank;
4587b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
4588b0c7d250SStefano Zampini       cols = adjncy;
4589b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
4590b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
4591b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
4592b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4593b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
459452e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
459552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
459652e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4597b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
4598b0c7d250SStefano Zampini     } else {
4599306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
4600b0c7d250SStefano Zampini     }
460122b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
4602e7931f94SStefano Zampini 
4603e7931f94SStefano Zampini     /* Partition */
4604306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
4605e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
4606e7931f94SStefano Zampini     if (use_vwgt) {
46073837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
4608e7931f94SStefano Zampini       v_wgt[0] = local_size;
4609e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
4610c8587f34SStefano Zampini     }
461128143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
461228143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
4613e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
4614e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
461522b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
4616e7931f94SStefano Zampini 
461752e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
461852e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
461952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
462052e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4621b0c7d250SStefano Zampini     if (!redprocs) {
4622b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
462328143c3dSStefano Zampini     } else {
4624b0c7d250SStefano Zampini       PetscInt    idxs[1];
4625b0c7d250SStefano Zampini       PetscMPIInt tag;
4626b0c7d250SStefano Zampini       MPI_Request *reqs;
4627b0c7d250SStefano Zampini 
4628b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
4629b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
4630b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
4631b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
463228143c3dSStefano Zampini       }
4633b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
4634b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4635b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
4636b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
4637e7931f94SStefano Zampini     }
463852e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4639e7931f94SStefano Zampini     /* clean up */
4640e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
464152e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
4642e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
4643e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
4644e7931f94SStefano Zampini   }
4645e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
4646e7931f94SStefano Zampini 
4647e7931f94SStefano Zampini   /* assemble parallel IS for sends */
4648e7931f94SStefano Zampini   i = 1;
4649e7931f94SStefano Zampini   if (color) i=0;
4650e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
4651e7931f94SStefano Zampini   /* get back IS */
4652e7931f94SStefano Zampini   *is_sends = ranks_send_to;
4653e7931f94SStefano Zampini   PetscFunctionReturn(0);
4654e7931f94SStefano Zampini }
4655e7931f94SStefano Zampini 
4656e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
4657e7931f94SStefano Zampini 
4658e7931f94SStefano Zampini #undef __FUNCT__
4659e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
466053a05cb3SStefano 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[])
4661e7931f94SStefano Zampini {
466270cf5478SStefano Zampini   Mat                    local_mat;
4663e7931f94SStefano Zampini   IS                     is_sends_internal;
46649d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
466528143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
46669d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
4667e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
4668e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
4669e7931f94SStefano Zampini   const PetscInt*        is_indices;
4670e7931f94SStefano Zampini   MatType                new_local_type;
4671e7931f94SStefano Zampini   /* buffers */
4672e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
467328143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
46749d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
4675e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
4676e7931f94SStefano Zampini   /* MPI */
467728143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
467828143c3dSStefano Zampini   PetscSubcomm           subcomm;
4679e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
468028143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
468128143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
468228143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
468328143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
468428143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
4685e7931f94SStefano Zampini   PetscErrorCode         ierr;
4686e7931f94SStefano Zampini 
4687e7931f94SStefano Zampini   PetscFunctionBegin;
468828143c3dSStefano Zampini   /* TODO: add missing checks */
468928143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
469028143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
469128143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
469228143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
4693e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
469428143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
4695e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4696e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
4697e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
4698e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
4699e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
470028143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
470170cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
470270cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
470328143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
470470cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
470570cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
470670cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
470770cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
470870cf5478SStefano Zampini   }
4709e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
4710e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
4711e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
4712e7931f94SStefano Zampini   if (!is_sends) {
471328143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
4714b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
4715c8587f34SStefano Zampini   } else {
4716e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
4717e7931f94SStefano Zampini     is_sends_internal = is_sends;
4718c8587f34SStefano Zampini   }
4719e7931f94SStefano Zampini 
4720e7931f94SStefano Zampini   /* get comm */
4721a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4722e7931f94SStefano Zampini 
4723e7931f94SStefano Zampini   /* compute number of sends */
4724e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4725e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4726e7931f94SStefano Zampini 
4727e7931f94SStefano Zampini   /* compute number of receives */
4728e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4729785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4730e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4731e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4732e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4733e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4734e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
4735e7931f94SStefano Zampini 
473628143c3dSStefano Zampini   /* restrict comm if requested */
473728143c3dSStefano Zampini   subcomm = 0;
473828143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
473928143c3dSStefano Zampini   if (restrict_comm) {
4740779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
4741779c1cceSStefano Zampini 
474228143c3dSStefano Zampini     color = 0;
474353a05cb3SStefano Zampini     if (restrict_full) {
474453a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
474553a05cb3SStefano Zampini     } else {
474653a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
474753a05cb3SStefano Zampini     }
474828143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
474928143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
475028143c3dSStefano Zampini     /* check if reuse has been requested */
475128143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
475228143c3dSStefano Zampini       if (*mat_n) {
475328143c3dSStefano Zampini         PetscMPIInt subcommsize2;
475428143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
475528143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
475628143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
475728143c3dSStefano Zampini       } else {
475828143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
475928143c3dSStefano Zampini       }
476028143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
4761779c1cceSStefano Zampini       PetscMPIInt rank;
4762779c1cceSStefano Zampini 
4763779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
476428143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
476528143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
476628143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4767306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
476828143c3dSStefano Zampini     }
476928143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
477028143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
477128143c3dSStefano Zampini   } else {
477228143c3dSStefano Zampini     comm_n = comm;
477328143c3dSStefano Zampini   }
477428143c3dSStefano Zampini 
4775e7931f94SStefano Zampini   /* prepare send/receive buffers */
4776785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4777e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4778785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4779e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
478028143c3dSStefano Zampini   if (nis) {
4781854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
478228143c3dSStefano Zampini   }
4783e7931f94SStefano Zampini 
478428143c3dSStefano Zampini   /* Get data from local matrices */
4785e7931f94SStefano Zampini   if (!isdense) {
4786a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4787e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4788e7931f94SStefano Zampini     /*
4789e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4790e7931f94SStefano Zampini        send_buffer_idxs should contain:
4791e7931f94SStefano Zampini        - MatType_PRIVATE type
4792e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4793e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4794e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4795e7931f94SStefano Zampini     */
4796e7931f94SStefano Zampini   } else {
4797e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
47983bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4799854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4800e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4801e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
48023bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4803e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
48043bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4805e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4806e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4807e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4808e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4809c8587f34SStefano Zampini     }
4810c8587f34SStefano Zampini   }
4811e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
481228143c3dSStefano Zampini   /* additional is (if any) */
481328143c3dSStefano Zampini   if (nis) {
481428143c3dSStefano Zampini     PetscMPIInt psum;
481528143c3dSStefano Zampini     PetscInt j;
481628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
481728143c3dSStefano Zampini       PetscInt plen;
481828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
481928143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
482028143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
482128143c3dSStefano Zampini     }
4822854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
482328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
482428143c3dSStefano Zampini       PetscInt plen;
482528143c3dSStefano Zampini       const PetscInt *is_array_idxs;
482628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
482728143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
482828143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
482928143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
483028143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
483128143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
483228143c3dSStefano Zampini     }
483328143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
483428143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
483528143c3dSStefano Zampini     }
483628143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
483728143c3dSStefano Zampini   }
483828143c3dSStefano Zampini 
4839e7931f94SStefano Zampini   buf_size_idxs = 0;
4840e7931f94SStefano Zampini   buf_size_vals = 0;
484128143c3dSStefano Zampini   buf_size_idxs_is = 0;
4842e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4843e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4844e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
484528143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4846e7931f94SStefano Zampini   }
4847785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4848785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
484995ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4850e7931f94SStefano Zampini 
4851e7931f94SStefano Zampini   /* get new tags for clean communications */
4852e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4853e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
485428143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4855e7931f94SStefano Zampini 
4856e7931f94SStefano Zampini   /* allocate for requests */
4857785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4858785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
485995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4860785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4861785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
486295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4863e7931f94SStefano Zampini 
4864e7931f94SStefano Zampini   /* communications */
4865e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4866e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
486728143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4868e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4869e7931f94SStefano Zampini     source_dest = onodes[i];
4870e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4871e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4872e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4873e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
487428143c3dSStefano Zampini     if (nis) {
487528143c3dSStefano 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);
487628143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
487728143c3dSStefano Zampini     }
4878e7931f94SStefano Zampini   }
4879e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4880e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4881e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4882e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
488328143c3dSStefano Zampini     if (nis) {
488428143c3dSStefano 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);
488528143c3dSStefano Zampini     }
4886e7931f94SStefano Zampini   }
4887e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4888e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4889e7931f94SStefano Zampini 
4890e7931f94SStefano Zampini   /* assemble new l2g map */
4891e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4892e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
48939d30be91SStefano Zampini   new_local_rows = 0;
4894e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
48959d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4896e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4897e7931f94SStefano Zampini   }
48989d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4899e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
49009d30be91SStefano Zampini   new_local_rows = 0;
4901e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
49029d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
49039d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4904e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4905e7931f94SStefano Zampini   }
49069d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
49079d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4908e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4909e7931f94SStefano Zampini 
4910e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4911e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4912e7931f94SStefano 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) */
4913e7931f94SStefano Zampini   if (n_recvs) {
491428143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4915e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4916e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4917e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4918e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4919e7931f94SStefano Zampini         break;
4920e7931f94SStefano Zampini       }
4921e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4922e7931f94SStefano Zampini     }
4923e7931f94SStefano Zampini     switch (new_local_type_private) {
492428143c3dSStefano Zampini       case MATDENSE_PRIVATE:
492528143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4926e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4927e7931f94SStefano Zampini           bs = 1;
492828143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
492928143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
493028143c3dSStefano Zampini           bs = 1;
493128143c3dSStefano Zampini         }
4932e7931f94SStefano Zampini         break;
4933e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4934e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4935e7931f94SStefano Zampini         bs = 1;
4936e7931f94SStefano Zampini         break;
4937e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4938e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4939e7931f94SStefano Zampini         break;
4940e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4941e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4942e7931f94SStefano Zampini         break;
4943e7931f94SStefano Zampini       default:
49449d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4945e7931f94SStefano Zampini         break;
4946e7931f94SStefano Zampini     }
494728143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
494828143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
494928143c3dSStefano Zampini     bs = 1;
4950e7931f94SStefano Zampini   }
4951e7931f94SStefano Zampini 
495270cf5478SStefano Zampini   /* create MATIS object if needed */
495370cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4954e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4955e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
495670cf5478SStefano Zampini   } else {
495770cf5478SStefano Zampini     /* it also destroys the local matrices */
495870cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
495970cf5478SStefano Zampini   }
496070cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4961e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
49629d30be91SStefano Zampini 
49639d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
49649d30be91SStefano Zampini 
49659d30be91SStefano Zampini   /* Global to local map of received indices */
49669d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
49679d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
49689d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
49699d30be91SStefano Zampini 
49709d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
49719d30be91SStefano Zampini   buf_size_idxs = 0;
49729d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
49739d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
49749d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
49759d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
49769d30be91SStefano Zampini   }
49779d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
49789d30be91SStefano Zampini 
49799d30be91SStefano Zampini   /* set preallocation */
49809d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
49819d30be91SStefano Zampini   if (!newisdense) {
49829d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
49839d30be91SStefano Zampini 
49849d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
49859d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
49869d30be91SStefano Zampini     if (n_recvs) {
49879d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
49889d30be91SStefano Zampini     }
49899d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
49909d30be91SStefano Zampini       PetscInt j;
49919d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
49929d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
49939d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
49949d30be91SStefano Zampini         }
49959d30be91SStefano Zampini       } else {
49969d30be91SStefano Zampini         /* TODO */
49979d30be91SStefano Zampini       }
49989d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
49999d30be91SStefano Zampini     }
50009d30be91SStefano Zampini     if (new_local_nnz) {
50019d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
50029d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
50039d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
50049d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
50059d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
50069d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
50079d30be91SStefano Zampini     } else {
50089d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
50099d30be91SStefano Zampini     }
50109d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
50119d30be91SStefano Zampini   } else {
50129d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
50139d30be91SStefano Zampini   }
5014e7931f94SStefano Zampini 
5015e7931f94SStefano Zampini   /* set values */
5016e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
50179d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5018e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5019e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5020e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
50219d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5022e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5023e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5024e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
502528143c3dSStefano Zampini     } else {
502628143c3dSStefano Zampini       /* TODO */
5027e7931f94SStefano Zampini     }
5028e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5029e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5030e7931f94SStefano Zampini   }
5031e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5032e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
503370cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
503470cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
50359d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
50369d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5037e7931f94SStefano Zampini 
5038dfd14d43SStefano Zampini #if 0
503928143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5040e7931f94SStefano Zampini     Vec       lvec,rvec;
5041e7931f94SStefano Zampini     PetscReal infty_error;
5042e7931f94SStefano Zampini 
50432a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5044e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5045e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5046e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
504770cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5048e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5049e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5050e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5051e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5052e7931f94SStefano Zampini   }
505328143c3dSStefano Zampini #endif
5054e7931f94SStefano Zampini 
505528143c3dSStefano Zampini   /* assemble new additional is (if any) */
505628143c3dSStefano Zampini   if (nis) {
505728143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
505828143c3dSStefano Zampini 
505928143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5060854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
506128143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
506228143c3dSStefano Zampini     psum = 0;
506328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
506428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
506528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
506628143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
506728143c3dSStefano Zampini         psum += plen;
506828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
506928143c3dSStefano Zampini       }
507028143c3dSStefano Zampini     }
5071854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5072854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
507328143c3dSStefano Zampini     for (i=1;i<nis;i++) {
507428143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
507528143c3dSStefano Zampini     }
507628143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
507728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
507828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
507928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
508028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
508128143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
508228143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
508328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
508428143c3dSStefano Zampini       }
508528143c3dSStefano Zampini     }
508628143c3dSStefano Zampini     for (i=0;i<nis;i++) {
508728143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
508828143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
508928143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
509028143c3dSStefano Zampini     }
509128143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
509228143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
509328143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
509428143c3dSStefano Zampini   }
5095e7931f94SStefano Zampini   /* free workspace */
509628143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5097e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5098e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5099e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5100e7931f94SStefano Zampini   if (isdense) {
5101e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5102e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5103e7931f94SStefano Zampini   } else {
5104e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5105e7931f94SStefano Zampini   }
510628143c3dSStefano Zampini   if (nis) {
510728143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
510828143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
510928143c3dSStefano Zampini   }
5110e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5111e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
511228143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5113e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5114e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
511528143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5116e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5117e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5118e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5119e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5120e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
512128143c3dSStefano Zampini   if (nis) {
512228143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
512328143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
512428143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
512528143c3dSStefano Zampini   }
512628143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
512728143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
512828143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
512928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
513028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
513128143c3dSStefano Zampini     }
513253a05cb3SStefano Zampini     *mat_n = NULL;
513328143c3dSStefano Zampini   }
5134e7931f94SStefano Zampini   PetscFunctionReturn(0);
5135e7931f94SStefano Zampini }
5136a57a6d2fSStefano Zampini 
513712edc857SStefano Zampini /* temporary hack into ksp private data structure */
5138af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
513912edc857SStefano Zampini 
5140c8587f34SStefano Zampini #undef __FUNCT__
5141c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5142c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5143c8587f34SStefano Zampini {
5144c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5145c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
514620a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
51479881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
514820a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
51496e683305SStefano Zampini   IS                     coarse_is,*isarray;
51506e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
515130368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5152f9eb5b7dSStefano Zampini   PC                     pc_temp;
5153c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5154c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5155f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
51564f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
51576e683305SStefano Zampini   Mat                    t_coarse_mat_is;
51586e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
51596e683305SStefano Zampini   PetscMPIInt            all_procs;
516074e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
516168457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
516222bc73bbSStefano Zampini   PetscScalar            *array;
51639881197aSStefano Zampini   PetscErrorCode         ierr;
5164fdc09c96SStefano Zampini 
5165c8587f34SStefano Zampini   PetscFunctionBegin;
5166c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
516768457ee5SStefano 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 */
5168fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
51695a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5170fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5171f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5172f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5173f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5174fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
517551bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
517651bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5177dc4bcba2SStefano Zampini         PC        pc;
5178dc4bcba2SStefano Zampini         PetscBool isbddc;
5179dc4bcba2SStefano Zampini 
5180dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5181dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5182dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5183dc4bcba2SStefano Zampini         if (isbddc) {
5184dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
5185dc4bcba2SStefano Zampini         }
5186727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
5187fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5188fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5189fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5190f4ddd8eeSStefano Zampini       }
5191fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5192fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5193f4ddd8eeSStefano Zampini     }
519470cf5478SStefano Zampini     /* reset any subassembling information */
519570cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
51966e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
51976e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5198fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5199f4ddd8eeSStefano Zampini   }
5200c8587f34SStefano Zampini 
52016e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
52022b510759SStefano Zampini   im_active = !!(pcis->n);
52032b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
52046e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
52056e683305SStefano Zampini   void_procs = all_procs-active_procs;
52066e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
520774e2c79eSStefano Zampini   redist = PETSC_FALSE;
520822bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
52096e683305SStefano Zampini     csin_ml = PETSC_TRUE;
52106e683305SStefano Zampini     ncoarse_ml = void_procs;
5211779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
5212779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
52136e683305SStefano Zampini       csin_ds = PETSC_TRUE;
521418a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
521518a45a71SStefano Zampini       redist = PETSC_TRUE;
521618a45a71SStefano Zampini     } else {
52176e683305SStefano Zampini       csin_ds = PETSC_TRUE;
5218779c1cceSStefano Zampini       ncoarse_ds = active_procs;
5219779c1cceSStefano Zampini       redist = PETSC_TRUE;
522018a45a71SStefano Zampini     }
52216e683305SStefano Zampini   } else {
52226e683305SStefano Zampini     csin_ml = PETSC_FALSE;
52236e683305SStefano Zampini     ncoarse_ml = all_procs;
52246e683305SStefano Zampini     if (void_procs) {
52256e683305SStefano Zampini       csin_ds = PETSC_TRUE;
52266e683305SStefano Zampini       ncoarse_ds = void_procs;
52276e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
52286e683305SStefano Zampini     } else {
5229779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
523074e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
523174e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
523274e2c79eSStefano Zampini         redist = PETSC_TRUE;
523374e2c79eSStefano Zampini       } else {
52346e683305SStefano Zampini         csin_ds = PETSC_FALSE;
52356e683305SStefano Zampini         ncoarse_ds = all_procs;
52366e683305SStefano Zampini       }
52376e683305SStefano Zampini     }
523874e2c79eSStefano Zampini   }
52396e683305SStefano Zampini 
52406e683305SStefano Zampini   /*
52416e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
52426e683305SStefano Zampini     - we have not exceeded the number of levels requested
52436e683305SStefano Zampini     - we can actually subassemble the active processes
52446e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
52456e683305SStefano Zampini   */
52466e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
52476e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
52486e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
52496e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
52506e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
5251f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
52522b510759SStefano Zampini     } else {
5253f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
5254c8587f34SStefano Zampini     }
5255c8587f34SStefano Zampini   }
52566e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
52576e683305SStefano Zampini   if (multilevel_allowed) {
52586e683305SStefano Zampini     ncoarse = ncoarse_ml;
52596e683305SStefano Zampini     csin = csin_ml;
526058da7f69SStefano Zampini     redist = PETSC_FALSE;
52616e683305SStefano Zampini   } else {
52626e683305SStefano Zampini     ncoarse = ncoarse_ds;
52636e683305SStefano Zampini     csin = csin_ds;
52646e683305SStefano Zampini   }
5265e7931f94SStefano Zampini 
5266abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5267abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5268abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5269abbbba34SStefano Zampini 
5270abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
527122bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
527222bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
527322bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
527422bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5275e176bc59SStefano 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);
52766e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
52776e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
52786e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5279abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5280abbbba34SStefano Zampini 
52816e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
528230368db7SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local))) { /* protects from unneded computations */
52836e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
52846e683305SStefano Zampini     const PetscInt         *idxs;
52856e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
52866e683305SStefano Zampini 
52876e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
52880be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
52896e683305SStefano Zampini     /* allocate space for temporary storage */
5290854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5291854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
52926e683305SStefano Zampini     /* allocate for IS array */
52936e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
52946e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
529530368db7SStefano Zampini     nisvert = 0;
529630368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
529730368db7SStefano Zampini       nisvert = 1;
529830368db7SStefano Zampini     }
529930368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5300854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
53016e683305SStefano Zampini     /* dofs splitting */
53026e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
53036e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
53046e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
53056e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
53066e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
53076e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
53086e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
530930368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
53106e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
53116e683305SStefano Zampini     }
53126e683305SStefano Zampini     /* neumann boundaries */
53136e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
53146e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
53156e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
53166e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
53176e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
53186e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
53196e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
532030368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
53216e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
53226e683305SStefano Zampini     }
532330368db7SStefano Zampini     /* primal vertices (benign) */
532430368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
532530368db7SStefano Zampini       ierr = ISGetLocalSize(pcbddc->user_primal_vertices_local,&tsize);CHKERRQ(ierr);
532630368db7SStefano Zampini       ierr = ISGetIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
532730368db7SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
532830368db7SStefano Zampini       ierr = ISRestoreIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
532930368db7SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
533030368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nis-1]);CHKERRQ(ierr);
533130368db7SStefano Zampini     }
53326e683305SStefano Zampini     /* free memory */
53336e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
53346e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
53356e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
53366e683305SStefano Zampini   } else {
53376e683305SStefano Zampini     nis = 0;
53386e683305SStefano Zampini     nisdofs = 0;
53396e683305SStefano Zampini     nisneu = 0;
534030368db7SStefano Zampini     nisvert = 0;
53416e683305SStefano Zampini     isarray = NULL;
53426e683305SStefano Zampini   }
53436e683305SStefano Zampini   /* destroy no longer needed map */
53446e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
53456e683305SStefano Zampini 
53466e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
53476e683305SStefano Zampini   coarse_mat_is = NULL;
53486e683305SStefano Zampini   if (csin) {
53496e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
535074e2c79eSStefano Zampini       if (redist) {
535174e2c79eSStefano Zampini         PetscMPIInt rank;
5352779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
535374e2c79eSStefano Zampini 
535474e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
535558da7f69SStefano Zampini         spc = active_procs/ncoarse;
535658da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
5357779c1cceSStefano Zampini         if (im_active) {
5358779c1cceSStefano Zampini           destsize = 1;
535974e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
536074e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
536174e2c79eSStefano Zampini           } else {
536274e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
536374e2c79eSStefano Zampini           }
536474e2c79eSStefano Zampini         } else {
5365779c1cceSStefano Zampini           destsize = 0;
53666e683305SStefano Zampini         }
5367779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5368779c1cceSStefano Zampini       } else if (csin_type_simple) {
53696e683305SStefano Zampini         PetscMPIInt rank;
53706e683305SStefano Zampini         PetscInt    issize,isidx;
5371779c1cceSStefano Zampini 
53726e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
53736e683305SStefano Zampini         if (im_active) {
53746e683305SStefano Zampini           issize = 1;
53756e683305SStefano Zampini           isidx = (PetscInt)rank;
53766e683305SStefano Zampini         } else {
53776e683305SStefano Zampini           issize = 0;
53786e683305SStefano Zampini           isidx = -1;
53796e683305SStefano Zampini         }
53806e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5381779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
5382b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
53836e683305SStefano Zampini       }
5384779c1cceSStefano Zampini 
5385779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
5386779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
5387779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
5388779c1cceSStefano Zampini         PetscInt *coarse_candidates;
5389779c1cceSStefano Zampini         const PetscInt* tisindices;
5390779c1cceSStefano Zampini 
5391779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
5392779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
5393779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5394779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
5395779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
5396779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
5397779c1cceSStefano Zampini           }
5398779c1cceSStefano Zampini         }
5399779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
5400779c1cceSStefano Zampini 
5401779c1cceSStefano Zampini 
54026e683305SStefano Zampini         if (pcbddc->dbg_flag) {
54036e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54046e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
54056e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
54066e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
5407779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
54086e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
54096e683305SStefano Zampini           }
54106e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
54116e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54126e683305SStefano Zampini         }
54136e683305SStefano Zampini         /* shift the pattern on coarse candidates */
54146e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
54156e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
5416854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
54176e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
54186e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
54196e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
54206e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
54216e683305SStefano Zampini       }
54226e683305SStefano Zampini       if (pcbddc->dbg_flag) {
54236e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54246e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
54256e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
54266e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54276e683305SStefano Zampini       }
5428779c1cceSStefano Zampini     }
54296e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
543053a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
543153a05cb3SStefano 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);
543253a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
543353a05cb3SStefano 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);
543453a05cb3SStefano Zampini     }
54356e683305SStefano Zampini   } else {
54366e683305SStefano Zampini     if (pcbddc->dbg_flag) {
54376e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54386e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
54396e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54406e683305SStefano Zampini     }
54416e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
54426e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
54436e683305SStefano Zampini   }
54446e683305SStefano Zampini 
54456e683305SStefano Zampini   /* create local to global scatters for coarse problem */
544668457ee5SStefano Zampini   if (compute_vecs) {
54476e683305SStefano Zampini     PetscInt lrows;
54486e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
54496e683305SStefano Zampini     if (coarse_mat_is) {
54506e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
54516e683305SStefano Zampini     } else {
54526e683305SStefano Zampini       lrows = 0;
54536e683305SStefano Zampini     }
54546e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
54556e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
54566e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
54576e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
54586e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
54596e683305SStefano Zampini   }
54606e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
54616e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
5462c8587f34SStefano Zampini 
5463f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5464f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5465f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5466f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5467f9eb5b7dSStefano Zampini   } else {
5468f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5469f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5470c8587f34SStefano Zampini   }
5471c8587f34SStefano Zampini 
54726e683305SStefano Zampini   /* print some info if requested */
54736e683305SStefano Zampini   if (pcbddc->dbg_flag) {
54746e683305SStefano Zampini     if (!multilevel_allowed) {
54756e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54766e683305SStefano Zampini       if (multilevel_requested) {
54776e683305SStefano 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);
54786e683305SStefano Zampini       } else if (pcbddc->max_levels) {
54796e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
54806e683305SStefano Zampini       }
54816e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54826e683305SStefano Zampini     }
54836e683305SStefano Zampini   }
54846e683305SStefano Zampini 
5485f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
54866e683305SStefano Zampini   if (coarse_mat_is) {
54876e683305SStefano Zampini     MatReuse coarse_mat_reuse;
54886a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
54896e683305SStefano Zampini     if (pcbddc->dbg_flag) {
54906e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
54916e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
54926e683305SStefano Zampini     }
5493f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5494312be037SStefano Zampini       char prefix[256],str_level[16];
5495e604994aSStefano Zampini       size_t len;
54966e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5497422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5498c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5499f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
55005f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
5501c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
55026e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5503c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5504c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5505e604994aSStefano Zampini       /* prefix */
5506e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5507e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5508e604994aSStefano Zampini       if (!pcbddc->current_level) {
5509e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5510e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5511c8587f34SStefano Zampini       } else {
5512e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5513312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5514312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
551534d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5516312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5517e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5518e604994aSStefano Zampini       }
5519e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
55203e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
55213e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
55223e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
55233e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5524f9eb5b7dSStefano Zampini       /* allow user customization */
5525f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
55263e3c6dadSStefano Zampini     }
55273e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
552851bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
55293e3c6dadSStefano Zampini     if (nisdofs) {
55303e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
55313e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
55323e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
55333e3c6dadSStefano Zampini       }
55343e3c6dadSStefano Zampini     }
55353e3c6dadSStefano Zampini     if (nisneu) {
55363e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
55373e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5538312be037SStefano Zampini     }
553930368db7SStefano Zampini     if (nisvert) {
554030368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
554130368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
554230368db7SStefano Zampini     }
5543f9eb5b7dSStefano Zampini 
5544f9eb5b7dSStefano Zampini     /* get some info after set from options */
5545f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5546f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
55474f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
55486e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5549f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5550f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5551f9eb5b7dSStefano Zampini     }
555239f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
55534f3a063dSStefano Zampini     if (isredundant) {
55544f3a063dSStefano Zampini       KSP inner_ksp;
55554f3a063dSStefano Zampini       PC  inner_pc;
55564f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
55574f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
55584f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
55594f3a063dSStefano Zampini     }
5560f9eb5b7dSStefano Zampini 
5561f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
5562fa7f1dd8SStefano Zampini     if (coarse_reuse) {
556381d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
5564fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
55656e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
5566fa7f1dd8SStefano Zampini     } else {
55676e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
5568fa7f1dd8SStefano Zampini     }
5569c8587f34SStefano Zampini     if (isbddc || isnn) {
5570*d4d8cf7bSStefano Zampini       if (isbddc) { /* currently there's no API for this */
5571*d4d8cf7bSStefano Zampini         PC_BDDC* pcbddc = (PC_BDDC*)pc_temp->data;
5572*d4d8cf7bSStefano Zampini         pcbddc->detect_disconnected = PETSC_TRUE;
5573*d4d8cf7bSStefano Zampini       }
557422bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
557570cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
5576b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
557722b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
55786e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
55796e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
55806e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
55816e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
558222b6e8a2SStefano Zampini           }
558370cf5478SStefano Zampini         }
558453a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
558570cf5478SStefano Zampini       } else {
558622bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
558722bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
558822bc73bbSStefano Zampini       }
558922bc73bbSStefano Zampini     } else {
55902e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
5591c8587f34SStefano Zampini     }
5592c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
5593c8587f34SStefano Zampini 
55943301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
55955a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
55963301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
55973301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
55983301b35fSStefano Zampini     }
55993301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
56003301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
56013301b35fSStefano Zampini     }
56023301b35fSStefano Zampini     if (pc->pmat->spd_set) {
56033301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
56043301b35fSStefano Zampini     }
56056e683305SStefano Zampini     /* set operators */
56065f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
56076e683305SStefano Zampini     if (pcbddc->dbg_flag) {
56086e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
56096e683305SStefano Zampini     }
56106e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
56116e683305SStefano Zampini     coarse_mat = 0;
56126e683305SStefano Zampini   }
56136e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
5614b1ecc7b1SStefano Zampini #if 0
5615b9b85e73SStefano Zampini   {
5616b9b85e73SStefano Zampini     PetscViewer viewer;
5617b9b85e73SStefano Zampini     char filename[256];
5618b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
5619b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
5620b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5621b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
5622b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5623b9b85e73SStefano Zampini   }
5624b9b85e73SStefano Zampini #endif
5625c8587f34SStefano Zampini 
5626c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
5627298c0119SStefano Zampini #if 0
5628c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
5629c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
563098a51de6SStefano Zampini   }
5631298c0119SStefano Zampini #endif
5632b0f5fe93SStefano Zampini   /* hack */
563398a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
563498a51de6SStefano Zampini     Vec crhs,csol;
563504708bb6SStefano Zampini 
5636f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
5637f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
5638f347579bSStefano Zampini     if (!csol) {
56392a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
5640f9eb5b7dSStefano Zampini     }
5641f347579bSStefano Zampini     if (!crhs) {
56422a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
5643f347579bSStefano Zampini     }
5644b0f5fe93SStefano Zampini   }
5645b0f5fe93SStefano Zampini 
5646b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
5647b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
5648b0f5fe93SStefano Zampini 
5649b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
56504f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
56514f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
56524f1b2e48SStefano Zampini     }
5653b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
5654b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
5655b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5656b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5657b0f5fe93SStefano Zampini     if (coarse_mat) {
5658b0f5fe93SStefano Zampini       Vec         nullv;
5659b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
5660b0f5fe93SStefano Zampini       PetscInt    nl;
5661b0f5fe93SStefano Zampini 
5662b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
5663b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
5664b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5665b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
5666b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
5667b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
5668b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5669b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
5670b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
5671b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
5672b0f5fe93SStefano Zampini     }
5673b0f5fe93SStefano Zampini   }
5674b0f5fe93SStefano Zampini 
5675b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
5676b0f5fe93SStefano Zampini     PetscBool ispreonly;
5677b0f5fe93SStefano Zampini 
5678b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
5679b0f5fe93SStefano Zampini       PetscBool isnull;
5680b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
5681*d4d8cf7bSStefano Zampini       if (0) {
568230368db7SStefano Zampini         if (isbddc && !pcbddc->benign_saddle_point) {
5683b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
5684b0f5fe93SStefano Zampini         } else {
5685b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
5686b0f5fe93SStefano Zampini         }
5687b0f5fe93SStefano Zampini       } else {
5688b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5689b0f5fe93SStefano Zampini       }
5690b0f5fe93SStefano Zampini     }
5691b0f5fe93SStefano Zampini     /* setup coarse ksp */
5692b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
5693cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
5694cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
56956e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
5696c8587f34SStefano Zampini       KSP       check_ksp;
56972b510759SStefano Zampini       KSPType   check_ksp_type;
5698c8587f34SStefano Zampini       PC        check_pc;
56996e683305SStefano Zampini       Vec       check_vec,coarse_vec;
57006a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
57012b510759SStefano Zampini       PetscInt  its;
57026e683305SStefano Zampini       PetscBool compute_eigs;
57036e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
57046e683305SStefano Zampini       PetscInt  neigs;
57058e185a42SStefano Zampini       const char *prefix;
5706c8587f34SStefano Zampini 
57072b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
57086e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
5709422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
571023ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5711f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
57122b510759SStefano Zampini       if (ispreonly) {
57132b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
57146e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
57152b510759SStefano Zampini       } else {
5716cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
57176e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
5718c8587f34SStefano Zampini       }
5719c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
57206e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
57216e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
57226e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
5723a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
5724a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
5725a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
5726a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
5727c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
5728c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
5729c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
5730c8587f34SStefano Zampini       /* create random vec */
57316e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
57326e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5733c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5734c8587f34SStefano Zampini       if (CoarseNullSpace) {
5735c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5736c8587f34SStefano Zampini       }
57376e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5738c8587f34SStefano Zampini       /* solve coarse problem */
57396e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5740c8587f34SStefano Zampini       if (CoarseNullSpace) {
57416e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5742c8587f34SStefano Zampini       }
5743cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
57446e683305SStefano Zampini       if (compute_eigs) {
5745854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5746854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
57476e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
57486e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
57496e683305SStefano Zampini         lambda_min = eigs_r[0];
57506e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
57516e683305SStefano Zampini           if (lambda_max>lambda_min) {
5752cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5753cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5754cbcc2c2aSStefano Zampini           }
5755c8587f34SStefano Zampini         }
5756c8587f34SStefano Zampini       }
5757cbcc2c2aSStefano Zampini 
5758c8587f34SStefano Zampini       /* check coarse problem residual error */
57596e683305SStefano Zampini       if (pcbddc->dbg_flag) {
57606e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
57616e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
57626e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5763c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
57646e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
57656e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5766c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5767779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
57686e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
57696e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
57706e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
57716e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5772b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
5773b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5774b0f5fe93SStefano Zampini         }
57756e683305SStefano Zampini         if (compute_eigs) {
57766e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
5777deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5778c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
57796e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
57806e683305SStefano 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);
57816e683305SStefano Zampini           for (i=0;i<neigs;i++) {
57826e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5783c8587f34SStefano Zampini           }
57846e683305SStefano Zampini         }
57856e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
57866e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
57876e683305SStefano Zampini       }
5788c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
57896e683305SStefano Zampini       if (compute_eigs) {
57906e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
57916e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5792c8587f34SStefano Zampini       }
57936e683305SStefano Zampini     }
57946e683305SStefano Zampini   }
5795cbcc2c2aSStefano Zampini   /* print additional info */
5796cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
57976e683305SStefano Zampini     /* waits until all processes reaches this point */
57986e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5799cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5800cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5801cbcc2c2aSStefano Zampini   }
5802cbcc2c2aSStefano Zampini 
58032b510759SStefano Zampini   /* free memory */
5804c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5805fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5806c8587f34SStefano Zampini   PetscFunctionReturn(0);
5807c8587f34SStefano Zampini }
5808674ae819SStefano Zampini 
5809f34684f1SStefano Zampini #undef __FUNCT__
5810f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5811f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5812f34684f1SStefano Zampini {
5813f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5814f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5815f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5816dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5817dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
581873be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5819dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5820f34684f1SStefano Zampini   PetscErrorCode ierr;
5821f34684f1SStefano Zampini 
5822f34684f1SStefano Zampini   PetscFunctionBegin;
5823f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
58240e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
58250e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5826727cdba6SStefano Zampini   }
5827dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
58283bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5829dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5830dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5831dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5832dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5833dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5834dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
58350e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
58360e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
58370e6343abSStefano Zampini   }
5838dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5839dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5840dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5841dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5842dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5843f34684f1SStefano Zampini 
5844f34684f1SStefano Zampini   /* check numbering */
5845f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5846019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5847dc456d91SStefano Zampini     PetscInt    i;
5848b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5849f34684f1SStefano Zampini 
5850f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5851f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5852f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
58531575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5854019a44ceSStefano Zampini     /* counter */
5855019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5856019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5857019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5858019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5859019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5860019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5861f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5862f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5863727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5864f34684f1SStefano Zampini     }
5865f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5866f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5867f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5868e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5869e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5870e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5871e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5872f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5873019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5874f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5875019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
587675c01103SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]);
587775c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
5878b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5879019a44ceSStefano 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);
5880f34684f1SStefano Zampini       }
5881f34684f1SStefano Zampini     }
5882019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5883b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5884f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5885f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5886f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5887f34684f1SStefano Zampini     }
5888f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5889f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5890e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5891e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5892f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5893f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5894b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5895ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5896ca8b9ea9SStefano Zampini 
5897ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
58983bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5899f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5900f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5901f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5902f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
59034bc2dc4bSStefano 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);
5904f34684f1SStefano Zampini       }
5905f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5906ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5907f34684f1SStefano Zampini     }
5908f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
59091575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5910302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5911f34684f1SStefano Zampini   }
59128bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5913f34684f1SStefano Zampini   /* get back data */
5914f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5915f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5916674ae819SStefano Zampini   PetscFunctionReturn(0);
5917674ae819SStefano Zampini }
5918674ae819SStefano Zampini 
5919e456f2a8SStefano Zampini #undef __FUNCT__
5920e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5921a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5922e456f2a8SStefano Zampini {
5923e456f2a8SStefano Zampini   IS             localis_t;
5924a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5925e456f2a8SStefano Zampini   PetscScalar    *vals;
5926e456f2a8SStefano Zampini   PetscErrorCode ierr;
5927e456f2a8SStefano Zampini 
5928e456f2a8SStefano Zampini   PetscFunctionBegin;
5929a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5930e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5931854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5932e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5933e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5934a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5935a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
59361035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5937a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
59381035eff8SStefano Zampini   }
5939a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5940e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5941e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5942a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5943a7dc3881SStefano Zampini   /* now compute set in local ordering */
5944a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5945a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5946a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5947a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5948a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5949ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5950e456f2a8SStefano Zampini       lsize++;
5951e456f2a8SStefano Zampini     }
5952e456f2a8SStefano Zampini   }
5953854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5954a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5955ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5956e456f2a8SStefano Zampini       idxs[lsize++] = i;
5957e456f2a8SStefano Zampini     }
5958e456f2a8SStefano Zampini   }
5959a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5960a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5961e456f2a8SStefano Zampini   *localis = localis_t;
5962e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5963e456f2a8SStefano Zampini }
5964906d46d4SStefano Zampini 
5965906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5966906d46d4SStefano Zampini #undef __FUNCT__
5967906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5968906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5969906d46d4SStefano Zampini {
5970906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5971906d46d4SStefano Zampini   PetscErrorCode   ierr;
5972906d46d4SStefano Zampini 
5973906d46d4SStefano Zampini   PetscFunctionBegin;
5974906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5975906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5976906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5977906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5978906d46d4SStefano Zampini   PetscFunctionReturn(0);
5979906d46d4SStefano Zampini }
5980906d46d4SStefano Zampini 
5981906d46d4SStefano Zampini #undef __FUNCT__
5982906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5983906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5984906d46d4SStefano Zampini {
5985906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5986906d46d4SStefano Zampini   PetscErrorCode   ierr;
5987906d46d4SStefano Zampini 
5988906d46d4SStefano Zampini   PetscFunctionBegin;
5989906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5990906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5991906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5992906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5993906d46d4SStefano Zampini   PetscFunctionReturn(0);
5994906d46d4SStefano Zampini }
5995b96c3477SStefano Zampini 
5996b96c3477SStefano Zampini #undef __FUNCT__
5997b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
599808122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5999b96c3477SStefano Zampini {
6000a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6001b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6002b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6003a64f4aa4SStefano Zampini   Mat                 S_j;
6004b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6005b96c3477SStefano Zampini   PetscBool           free_used_adj;
6006b96c3477SStefano Zampini   PetscErrorCode      ierr;
6007b96c3477SStefano Zampini 
6008b96c3477SStefano Zampini   PetscFunctionBegin;
6009b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6010b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
601108122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6012b96c3477SStefano Zampini     used_xadj = NULL;
6013b96c3477SStefano Zampini     used_adjncy = NULL;
6014b96c3477SStefano Zampini   } else {
601508122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
601608122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
601708122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
601808122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6019b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6020b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6021b96c3477SStefano Zampini     } else {
60222fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6023b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6024b96c3477SStefano Zampini       PetscInt       nvtxs;
6025b96c3477SStefano Zampini 
60262fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
60272fffb893SStefano Zampini       if (flg_row) {
6028b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6029b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6030b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6031b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
60322fffb893SStefano Zampini       } else {
60332fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
60342fffb893SStefano Zampini         used_xadj = NULL;
60352fffb893SStefano Zampini         used_adjncy = NULL;
60362fffb893SStefano Zampini       }
60372fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6038b96c3477SStefano Zampini     }
6039b96c3477SStefano Zampini   }
6040d5574798SStefano Zampini 
6041d5574798SStefano Zampini   /* setup sub_schurs data */
6042a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6043df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6044df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6045a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6046ca92afb2SStefano 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);
6047a64f4aa4SStefano Zampini   } else {
60486816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
604904708bb6SStefano Zampini     PetscBool isseqaij;
6050a3df083aSStefano Zampini     PetscInt  benign_n;
6051a3df083aSStefano Zampini 
60525feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
60535feab87aSStefano Zampini       PetscInt n_vertices;
60545feab87aSStefano Zampini 
60555feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
60562034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
60575feab87aSStefano Zampini     }
605804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
605904708bb6SStefano Zampini     if (!isseqaij) {
606004708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
606104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
606204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
606304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
606404708bb6SStefano Zampini       } else {
606504708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
606604708bb6SStefano Zampini       }
606704708bb6SStefano Zampini     }
6068a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6069a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6070ca92afb2SStefano Zampini     } else {
6071a3df083aSStefano Zampini       benign_n = 0;
6072ca92afb2SStefano Zampini     }
6073a3df083aSStefano 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);
6074ca92afb2SStefano Zampini   }
6075d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6076b96c3477SStefano Zampini 
6077b96c3477SStefano Zampini   /* free adjacency */
6078b96c3477SStefano Zampini   if (free_used_adj) {
6079b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6080b96c3477SStefano Zampini   }
6081b96c3477SStefano Zampini   PetscFunctionReturn(0);
6082b96c3477SStefano Zampini }
6083b96c3477SStefano Zampini 
6084b96c3477SStefano Zampini #undef __FUNCT__
6085b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
608608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6087b96c3477SStefano Zampini {
6088b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6089b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6090b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6091b96c3477SStefano Zampini   PCBDDCGraph         graph;
6092b96c3477SStefano Zampini   PetscErrorCode      ierr;
6093b96c3477SStefano Zampini 
6094b96c3477SStefano Zampini   PetscFunctionBegin;
6095b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
609608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
60973301b35fSStefano Zampini     IS       verticesIS,verticescomm;
60983301b35fSStefano Zampini     PetscInt vsize,*idxs;
6099b96c3477SStefano Zampini 
6100b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
61013301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
61023301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
61033301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
61043301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
61053301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6106b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
61077fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
61083301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
61093301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6110b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6111b96c3477SStefano Zampini /*
6112b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
6113b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6114b96c3477SStefano Zampini     }
6115b96c3477SStefano Zampini */
6116b96c3477SStefano Zampini   } else {
6117b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6118b96c3477SStefano Zampini   }
6119b96c3477SStefano Zampini 
6120b96c3477SStefano Zampini   /* sub_schurs init */
6121a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6122a64f4aa4SStefano Zampini 
6123b96c3477SStefano Zampini   /* free graph struct */
612408122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6125b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6126b96c3477SStefano Zampini   }
6127b96c3477SStefano Zampini   PetscFunctionReturn(0);
6128b96c3477SStefano Zampini }
6129fa34dd3eSStefano Zampini 
6130fa34dd3eSStefano Zampini #undef __FUNCT__
6131fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6132fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6133fa34dd3eSStefano Zampini {
6134fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6135fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6136fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6137fa34dd3eSStefano Zampini 
6138fa34dd3eSStefano Zampini   PetscFunctionBegin;
6139fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6140fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
61414f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6142fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
61434f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
614475c01103SStefano Zampini     PetscReal      norm;
6145fa34dd3eSStefano Zampini     PetscInt       i;
6146fa34dd3eSStefano Zampini 
6147fa34dd3eSStefano Zampini     /* B0 and B0_B */
6148fa34dd3eSStefano Zampini     if (zerodiag) {
6149fa34dd3eSStefano Zampini       IS       dummy;
6150fa34dd3eSStefano Zampini 
61514f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
61524f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6153fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6154fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6155fa34dd3eSStefano Zampini     }
6156fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6157fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6158fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6159fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6160fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6161fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6162fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6163fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6164fa34dd3eSStefano Zampini     /* S_j */
6165fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6166fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6167fa34dd3eSStefano Zampini 
6168fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6169fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6170fa34dd3eSStefano Zampini     /* continuous in primal space */
6171fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6172fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6173fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6174fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
61754f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
61764f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6177fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6178fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6179fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6180fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6181fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6182fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6183fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6184fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6185fa34dd3eSStefano Zampini 
6186fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6187fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6188fa34dd3eSStefano Zampini     /* local with Schur */
6189fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6190fa34dd3eSStefano Zampini     if (zerodiag) {
6191fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
61924f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6193fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6194fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6195fa34dd3eSStefano Zampini     }
6196fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6197fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6198fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6199fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6200fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6201fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6202fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6203fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6204fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6205fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6206fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6207fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6208fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6209fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6210fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6211fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6212fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6213fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6214fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6215fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6216fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6217fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6218fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6219fa34dd3eSStefano Zampini     if (zerodiag) {
6220fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6221fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
62224f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6223fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6224fa34dd3eSStefano Zampini     }
6225fa34dd3eSStefano Zampini     /* BDDC */
6226fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6227fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6228fa34dd3eSStefano Zampini 
6229fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6230fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6231fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6232fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
62334f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
62344f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6235fa34dd3eSStefano Zampini     }
62364f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6237fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6238fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6239fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6240fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6241fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6242fa34dd3eSStefano Zampini   }
6243fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6244fa34dd3eSStefano Zampini }
6245