xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 63c961ada8c05f6fcb9fc9a079c92912da5ff4ec)
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;
289*63c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
290*63c961adSStefano Zampini     *ncc = 0;
291*63c961adSStefano Zampini     *cc = NULL;
292*63c961adSStefano Zampini     PetscFunctionReturn(0);
293*63c961adSStefano Zampini   }
2944f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
2954f1b2e48SStefano Zampini   if (!isseqaij && filter) {
2961cf9b237SStefano Zampini     PetscBool isseqdense;
2971cf9b237SStefano Zampini 
2981cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
2991cf9b237SStefano Zampini     if (!isseqdense) {
3004f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
3011cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
3021cf9b237SStefano Zampini       PetscScalar *array;
3031cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
3041cf9b237SStefano Zampini 
3051cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
3061cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
3071cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
3081cf9b237SStefano Zampini       for (i=0;i<n;i++) {
3091cf9b237SStefano Zampini         PetscInt j;
3101cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
3111cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
3121cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
3131cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
3141cf9b237SStefano Zampini         }
3151cf9b237SStefano Zampini       }
3161cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
3171cf9b237SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_REUSE_MATRIX,&B);CHKERRQ(ierr);
3181cf9b237SStefano Zampini     }
3194f1b2e48SStefano Zampini   } else {
3204f1b2e48SStefano Zampini     B = A;
3214f1b2e48SStefano Zampini   }
3224f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3234f1b2e48SStefano Zampini 
3244f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
3254f1b2e48SStefano Zampini   if (filter) {
3264f1b2e48SStefano Zampini     PetscScalar *data;
3274f1b2e48SStefano Zampini     PetscInt    j,cum;
3284f1b2e48SStefano Zampini 
3294f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
3304f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
3314f1b2e48SStefano Zampini     cum = 0;
3324f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
3334f1b2e48SStefano Zampini       PetscInt t;
3344f1b2e48SStefano Zampini 
3354f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
3364f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
3374f1b2e48SStefano Zampini           continue;
3384f1b2e48SStefano Zampini         }
3394f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
3404f1b2e48SStefano Zampini       }
3414f1b2e48SStefano Zampini       t = xadj_filtered[i];
3424f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
3434f1b2e48SStefano Zampini       cum += t;
3444f1b2e48SStefano Zampini     }
3454f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
3464f1b2e48SStefano Zampini   } else {
3474f1b2e48SStefano Zampini     xadj_filtered = NULL;
3484f1b2e48SStefano Zampini     adjncy_filtered = NULL;
3494f1b2e48SStefano Zampini   }
3504f1b2e48SStefano Zampini 
3514f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
3524f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
3534f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
3544f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3554f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
3564f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
3574f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3584f1b2e48SStefano Zampini   if (xadj_filtered) {
3594f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
3604f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
3614f1b2e48SStefano Zampini   } else {
3624f1b2e48SStefano Zampini     graph->xadj = xadj;
3634f1b2e48SStefano Zampini     graph->adjncy = adjncy;
3644f1b2e48SStefano Zampini   }
3654f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
3664f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3674f1b2e48SStefano Zampini   /* partial clean up */
3684f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
3694f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3701cf9b237SStefano Zampini   if (A != B) {
3714f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
3724f1b2e48SStefano Zampini   }
3734f1b2e48SStefano Zampini 
3744f1b2e48SStefano Zampini   /* get back data */
3751cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
3761cf9b237SStefano Zampini   if (cc) {
3774f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
3784f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
3794f1b2e48SStefano 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);
3804f1b2e48SStefano Zampini     }
3814f1b2e48SStefano Zampini     *cc = cc_n;
3821cf9b237SStefano Zampini   }
3834f1b2e48SStefano Zampini   /* clean up graph */
3844f1b2e48SStefano Zampini   graph->xadj = 0;
3854f1b2e48SStefano Zampini   graph->adjncy = 0;
3864f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
3874f1b2e48SStefano Zampini   PetscFunctionReturn(0);
3884f1b2e48SStefano Zampini }
3894f1b2e48SStefano Zampini 
3904f1b2e48SStefano Zampini #undef __FUNCT__
3915408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
3925408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
3935408967cSStefano Zampini {
3945408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3955408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
396dee84bffSStefano Zampini   IS             dirIS = NULL;
3974f1b2e48SStefano Zampini   PetscInt       i;
3985408967cSStefano Zampini   PetscErrorCode ierr;
3995408967cSStefano Zampini 
4005408967cSStefano Zampini   PetscFunctionBegin;
401dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
4025408967cSStefano Zampini   if (zerodiag) {
4035408967cSStefano Zampini     Mat            A;
4045408967cSStefano Zampini     Vec            vec3_N;
4055408967cSStefano Zampini     PetscScalar    *vals;
4065408967cSStefano Zampini     const PetscInt *idxs;
407d12d3064SStefano Zampini     PetscInt       nz,*count;
4085408967cSStefano Zampini 
4095408967cSStefano Zampini     /* p0 */
4105408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
4115408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
4125408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
4135408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
4144f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
4155408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4165408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4175408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4185408967cSStefano Zampini     /* v_I */
4195408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
4205408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
4215408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4225408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
4235408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
4245408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
4255408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4265408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
4275408967cSStefano Zampini     if (dirIS) {
4285408967cSStefano Zampini       PetscInt n;
4295408967cSStefano Zampini 
4305408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
4315408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
4325408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
4335408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4345408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
4355408967cSStefano Zampini     }
4365408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
4375408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
4385408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
4395408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
4405408967cSStefano Zampini     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
4415408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
4425408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
4434f1b2e48SStefano Zampini     if (PetscAbsScalar(vals[0]) > PETSC_SMALL) {
4445408967cSStefano 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]));
4455408967cSStefano Zampini     }
4465408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
4475408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
448d12d3064SStefano Zampini 
449d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
450d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
451d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
452d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
453d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
454d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
455d4d8cf7bSStefano Zampini     for (i=0;i<nz;i++) {
456d12d3064SStefano Zampini       if (count[idxs[i]]) {
457d12d3064SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
458d12d3064SStefano Zampini       }
459d4d8cf7bSStefano Zampini     }
460d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
461d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
4625408967cSStefano Zampini   }
463dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
4645408967cSStefano Zampini 
4655408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
4665408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
4674f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
4685408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
4694f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
4705408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
4714f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
4724f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
4734f1b2e48SStefano 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);
4744f1b2e48SStefano Zampini     }
4755408967cSStefano Zampini   }
4765408967cSStefano Zampini   PetscFunctionReturn(0);
4775408967cSStefano Zampini }
4785408967cSStefano Zampini 
4795408967cSStefano Zampini #undef __FUNCT__
480339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
481339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
482339f8db1SStefano Zampini {
483339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4844f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
485b0f5fe93SStefano Zampini   PetscInt       nz,n;
4864f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
487339f8db1SStefano Zampini   PetscErrorCode ierr;
488339f8db1SStefano Zampini 
489339f8db1SStefano Zampini   PetscFunctionBegin;
4909f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
4919f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
492339f8db1SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
493a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
494a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
495a3df083aSStefano Zampini   }
496a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
497a3df083aSStefano Zampini   pcbddc->benign_n = 0;
4984f1b2e48SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
4994f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
5004f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
5014f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
5024f1b2e48SStefano Zampini      since the local Schur complements are SPD
5034f1b2e48SStefano Zampini   */
5044f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
5054f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
50640fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
5074f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
5084f1b2e48SStefano Zampini 
5094f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
5104f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
5114f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
5124f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
513ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
51440fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
51540fa8d13SStefano Zampini     if (!sorted) {
51640fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
51740fa8d13SStefano Zampini     }
51840fa8d13SStefano Zampini   } else {
51940fa8d13SStefano Zampini     pressures = NULL;
52040fa8d13SStefano Zampini   }
52197d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
52297d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
52397d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
524339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
525339f8db1SStefano Zampini   if (!sorted) {
526339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
527339f8db1SStefano Zampini   }
528339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5294f1b2e48SStefano Zampini   if (!nz) {
5304f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
5314f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
53240fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
53340fa8d13SStefano Zampini   }
5344f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
5354f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
5364f1b2e48SStefano Zampini   zerodiag_subs = NULL;
5374f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
5384f1b2e48SStefano Zampini   if (has_null_pressures) {
5394f1b2e48SStefano Zampini     IS       *subs;
5404f1b2e48SStefano Zampini     PetscInt nsubs,i;
5414f1b2e48SStefano Zampini 
5424f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
5434f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
5444f1b2e48SStefano Zampini     if (nsubs > 1) {
5454f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
5464f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
5474f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
5484f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
5494f1b2e48SStefano Zampini         PetscInt               nl;
5504f1b2e48SStefano Zampini 
5514f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
5524f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
5534f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
5544f1b2e48SStefano Zampini         if (nl) {
5554f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
5564f1b2e48SStefano Zampini 
5574f1b2e48SStefano Zampini           if (pressures) {
5584f1b2e48SStefano Zampini             IS t_pressure_subs;
5594f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
5604f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
5614f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
5624f1b2e48SStefano Zampini           }
5634f1b2e48SStefano Zampini           if (valid) {
5644f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
5654f1b2e48SStefano Zampini             pcbddc->benign_n++;
5664f1b2e48SStefano Zampini           } else {
5674f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
5684f1b2e48SStefano Zampini           }
5694f1b2e48SStefano Zampini         }
5704f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
5714f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
5724f1b2e48SStefano Zampini       }
5734f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
5744f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
5754f1b2e48SStefano Zampini       if (pressures) {
5764f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
5774f1b2e48SStefano Zampini       }
5784f1b2e48SStefano Zampini       if (valid) {
5794f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
580ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
5814f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
5824f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
5834f1b2e48SStefano Zampini       }
5844f1b2e48SStefano Zampini     }
5854f1b2e48SStefano Zampini   }
5864f1b2e48SStefano Zampini 
5874f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
5884f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
5894f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
5904f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
5914f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
5924f1b2e48SStefano Zampini   }
5934f1b2e48SStefano Zampini 
5944f1b2e48SStefano Zampini   /* final check for null pressures */
5954f1b2e48SStefano Zampini   if (zerodiag && pressures) {
5964f1b2e48SStefano Zampini     PetscInt nz,np;
5974f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5984f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
5994f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
6004f1b2e48SStefano Zampini   }
6014f1b2e48SStefano Zampini 
6024f1b2e48SStefano Zampini   if (recompute_zerodiag) {
6034f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
6044f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
6054f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
6064f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
6074f1b2e48SStefano Zampini     } else {
6084f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
6094f1b2e48SStefano Zampini 
6104f1b2e48SStefano Zampini       nzn = 0;
6114f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
6124f1b2e48SStefano Zampini         PetscInt ns;
6134f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
6144f1b2e48SStefano Zampini         nzn += ns;
6154f1b2e48SStefano Zampini       }
6164f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
6174f1b2e48SStefano Zampini       nzn = 0;
6184f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
6194f1b2e48SStefano Zampini         PetscInt ns,*idxs;
6204f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
6214f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
6224f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
6234f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
6244f1b2e48SStefano Zampini         nzn += ns;
6254f1b2e48SStefano Zampini       }
6264f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
6274f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
6284f1b2e48SStefano Zampini     }
6294f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
6304f1b2e48SStefano Zampini   }
6314f1b2e48SStefano Zampini 
6324f1b2e48SStefano Zampini   if (has_null_pressures) {
6334f1b2e48SStefano Zampini     IS             zerodiagc;
6344f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
6354f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
6364f1b2e48SStefano Zampini 
6374f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
638339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
639339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
640339f8db1SStefano Zampini     /* local change of basis for pressures */
641339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
64297d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
643339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
644339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
645339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
6464f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
6474f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
6484f1b2e48SStefano Zampini       PetscInt nzs,j;
6494f1b2e48SStefano Zampini 
6504f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
6514f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
6524f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
6534f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
6544f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
6554f1b2e48SStefano Zampini     }
656339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
657339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
658339f8db1SStefano Zampini     /* set identity on velocities */
659339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
660339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
661339f8db1SStefano Zampini     }
6624f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
6634f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
6649f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
6654f1b2e48SStefano 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);
666339f8db1SStefano Zampini     /* set change on pressures */
6674f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
6684f1b2e48SStefano Zampini       PetscScalar *array;
6694f1b2e48SStefano Zampini       PetscInt    nzs;
6704f1b2e48SStefano Zampini 
6714f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
6724f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
6734f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
674339f8db1SStefano Zampini         PetscScalar vals[2];
675339f8db1SStefano Zampini         PetscInt    cols[2];
676339f8db1SStefano Zampini 
677339f8db1SStefano Zampini         cols[0] = idxs[i];
6784f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
679339f8db1SStefano Zampini         vals[0] = 1.;
680b0f5fe93SStefano Zampini         vals[1] = 1.;
6814f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
682339f8db1SStefano Zampini       }
6834f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
6844f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
6854f1b2e48SStefano Zampini       array[nzs-1] = 1.;
6864f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
6874f1b2e48SStefano Zampini       /* store local idxs for p0 */
6884f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
6894f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
690339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
6914f1b2e48SStefano Zampini     }
692339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
693339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
694a3df083aSStefano Zampini     /* project if needed */
695a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
69697d764eeSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&pcbddc->benign_original_mat);CHKERRQ(ierr);
697339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
69897d764eeSStefano Zampini       ierr = MatSeqAIJCompress(pcbddc->benign_original_mat,&pcbddc->local_mat);CHKERRQ(ierr);
69997d764eeSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
700a3df083aSStefano Zampini     }
7014f1b2e48SStefano Zampini     /* store global idxs for p0 */
7024f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
703339f8db1SStefano Zampini   }
704ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
7054f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
706b0f5fe93SStefano Zampini 
707b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
708b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
709339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
710339f8db1SStefano Zampini   PetscFunctionReturn(0);
711339f8db1SStefano Zampini }
712339f8db1SStefano Zampini 
713339f8db1SStefano Zampini #undef __FUNCT__
714015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
715015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
716efc2fbd9SStefano Zampini {
717efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
718efc2fbd9SStefano Zampini   PetscErrorCode ierr;
719efc2fbd9SStefano Zampini 
720efc2fbd9SStefano Zampini   PetscFunctionBegin;
721efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
722efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
7234f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
724efc2fbd9SStefano Zampini   }
725015636ebSStefano Zampini   if (get) { /* use SF to get values */
726efc2fbd9SStefano Zampini     PetscScalar *array;
727efc2fbd9SStefano Zampini 
728efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
7294f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
7304f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
731efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
7324f1b2e48SStefano Zampini   } else { /* use VecSetValues (not scalable, I should try to find a better solution (defining a new MPI_OP for reduction) */
7334f1b2e48SStefano Zampini     ierr = VecSetValues(v,pcbddc->benign_n,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
734efc2fbd9SStefano Zampini     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
735efc2fbd9SStefano Zampini     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
736efc2fbd9SStefano Zampini   }
737efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
738efc2fbd9SStefano Zampini }
739efc2fbd9SStefano Zampini 
740efc2fbd9SStefano Zampini #undef __FUNCT__
741c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
742c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
743c263805aSStefano Zampini {
744c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
745c263805aSStefano Zampini   PetscErrorCode ierr;
746c263805aSStefano Zampini 
747c263805aSStefano Zampini   PetscFunctionBegin;
748c263805aSStefano Zampini   /* TODO: add error checking
749c263805aSStefano Zampini     - avoid nested pop (or push) calls.
750c263805aSStefano Zampini     - cannot push before pop.
7511c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
752c263805aSStefano Zampini   */
7534f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
754efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
755efc2fbd9SStefano Zampini   }
756c263805aSStefano Zampini   if (pop) {
757a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
7584f1b2e48SStefano Zampini       IS       is_p0;
7594f1b2e48SStefano Zampini       MatReuse reuse;
760c263805aSStefano Zampini 
761c263805aSStefano Zampini       /* extract B_0 */
7624f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
7634f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
7644f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
7654f1b2e48SStefano Zampini       }
7664f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
7674f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
768c263805aSStefano Zampini       /* remove rows and cols from local problem */
769c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
77097d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
7714f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
7724f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
773a3df083aSStefano Zampini     } else {
774a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
775a3df083aSStefano Zampini       PetscScalar *vals;
776a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
777a3df083aSStefano Zampini 
778a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
779a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
780a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
781a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
782a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
783a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
784a3df083aSStefano Zampini         /* this matrix is very sparse: the nnz pattern is not known unless we do 2 sweeps of the next loop.
785a3df083aSStefano Zampini            Setting nnz=100 should be more than enough */
786a3df083aSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,100,NULL);CHKERRQ(ierr);
787a3df083aSStefano Zampini       }
788a3df083aSStefano Zampini 
789a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
790a3df083aSStefano Zampini         PetscScalar *array;
791a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
792a3df083aSStefano Zampini 
793a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
794a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
795a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
796a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
797a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
798a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
799a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
800a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
801a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
802a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
803a3df083aSStefano Zampini         cum = 0;
804a3df083aSStefano Zampini         for (j=0;j<n;j++) {
805a3df083aSStefano Zampini           if (PetscUnlikely(PetscAbsReal(array[j]) > PETSC_SMALL)) {
806a3df083aSStefano Zampini             vals[cum] = array[j];
807a3df083aSStefano Zampini             idxs_ins[cum] = j;
808a3df083aSStefano Zampini             cum++;
809a3df083aSStefano Zampini           }
810a3df083aSStefano Zampini         }
811a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
812a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
813a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
814a3df083aSStefano Zampini       }
815a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
816a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
817a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
818a3df083aSStefano Zampini     }
819c263805aSStefano Zampini   } else { /* push */
820a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
8214f1b2e48SStefano Zampini       PetscInt i;
8224f1b2e48SStefano Zampini 
8234f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
8244f1b2e48SStefano Zampini         PetscScalar *B0_vals;
8254f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
8264f1b2e48SStefano Zampini 
8274f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
8284f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
8297b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
8304f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
8314f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
8324f1b2e48SStefano Zampini       }
833c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
834c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
835a3df083aSStefano Zampini     } else {
836a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
837a3df083aSStefano Zampini     }
838c263805aSStefano Zampini   }
839c263805aSStefano Zampini   PetscFunctionReturn(0);
840c263805aSStefano Zampini }
841c263805aSStefano Zampini 
842c263805aSStefano Zampini #undef __FUNCT__
843b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
84408122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
845b1b3d7a2SStefano Zampini {
846b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
84708122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
84808122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
84908122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
85008122e43SStefano Zampini   PetscScalar     *work,lwork;
85108122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
85208122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
85308122e43SStefano Zampini   PetscReal       *eigs,thresh;
8541b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
855f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
85608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
85708122e43SStefano Zampini   PetscReal       *rwork;
85808122e43SStefano Zampini #endif
859b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
860b1b3d7a2SStefano Zampini 
861b1b3d7a2SStefano Zampini   PetscFunctionBegin;
862df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
863df4d28bfSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
86408122e43SStefano Zampini   }
86508122e43SStefano Zampini 
86606a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
86706a4e24aSStefano 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);
86806a4e24aSStefano Zampini   }
86906a4e24aSStefano Zampini 
870fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
871fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
872fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
873fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
8741575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
875fd14bc51SStefano Zampini   }
876fd14bc51SStefano Zampini 
877e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
878e496cd5dSStefano 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);
879e496cd5dSStefano Zampini   }
880e496cd5dSStefano Zampini 
88108122e43SStefano Zampini   /* max size of subsets */
88208122e43SStefano Zampini   mss = 0;
88308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
88408122e43SStefano Zampini     PetscInt subset_size;
885862806e4SStefano Zampini 
88608122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
88708122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
88808122e43SStefano Zampini   }
88908122e43SStefano Zampini 
89008122e43SStefano Zampini   /* min/max and threshold */
89108122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
892f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
89308122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
894f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
895f6f667cfSStefano Zampini   if (nmin) {
896f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
897f6f667cfSStefano Zampini   }
89808122e43SStefano Zampini 
89908122e43SStefano Zampini   /* allocate lapack workspace */
90008122e43SStefano Zampini   cum = cum2 = 0;
90108122e43SStefano Zampini   maxneigs = 0;
90208122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
90308122e43SStefano Zampini     PetscInt n,subset_size;
904f6f667cfSStefano Zampini 
90508122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
90608122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
9079162d606SStefano Zampini     cum += subset_size;
9089162d606SStefano Zampini     cum2 += subset_size*n;
90908122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
91008122e43SStefano Zampini   }
91108122e43SStefano Zampini   if (mss) {
9129ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
91308122e43SStefano Zampini       PetscBLASInt B_itype = 1;
91408122e43SStefano Zampini       PetscBLASInt B_N = mss;
9154c6709b3SStefano Zampini       PetscReal    zero = 0.0;
9164c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
91708122e43SStefano Zampini 
91808122e43SStefano Zampini       B_lwork = -1;
91908122e43SStefano Zampini       S = NULL;
92008122e43SStefano Zampini       St = NULL;
921a58a30b4SStefano Zampini       eigs = NULL;
922a58a30b4SStefano Zampini       eigv = NULL;
923a58a30b4SStefano Zampini       B_iwork = NULL;
924a58a30b4SStefano Zampini       B_ifail = NULL;
925d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
926d1710679SStefano Zampini       rwork = NULL;
927d1710679SStefano Zampini #endif
9288bec7fa6SStefano Zampini       thresh = 1.0;
92908122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
93008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
93108122e43SStefano 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));
93208122e43SStefano Zampini #else
93308122e43SStefano 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));
93408122e43SStefano Zampini #endif
93508122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
93608122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
93708122e43SStefano Zampini     } else {
93808122e43SStefano Zampini         /* TODO */
93908122e43SStefano Zampini     }
94008122e43SStefano Zampini   } else {
94108122e43SStefano Zampini     lwork = 0;
94208122e43SStefano Zampini   }
94308122e43SStefano Zampini 
94408122e43SStefano Zampini   nv = 0;
945d62866d3SStefano 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) */
946d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
94708122e43SStefano Zampini   }
9484c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
949f6f667cfSStefano Zampini   if (allocated_S_St) {
950f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
951f6f667cfSStefano Zampini   }
952f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
95308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
95408122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
95508122e43SStefano Zampini #endif
9569162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
9579162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
9589162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
95908122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
9609162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
96108122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
96208122e43SStefano Zampini 
96308122e43SStefano Zampini   maxneigs = 0;
96408122e43SStefano Zampini   cum = cum2 = cumarray = 0;
9659162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
9669162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
967d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
96808122e43SStefano Zampini     const PetscInt *idxs;
96908122e43SStefano Zampini 
970d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
97108122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
97208122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
97308122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
97408122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
9759162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
9769162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
97708122e43SStefano Zampini     }
97808122e43SStefano Zampini     cum2 = cum;
979d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
98008122e43SStefano Zampini   }
98108122e43SStefano Zampini 
98208122e43SStefano Zampini   if (mss) { /* multilevel */
98308122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
98408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
98508122e43SStefano Zampini   }
98608122e43SStefano Zampini 
987ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
98808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
98908122e43SStefano Zampini     const PetscInt *idxs;
990f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
991862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
99208122e43SStefano Zampini     PetscBLASInt   B_N;
993aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
99408122e43SStefano Zampini 
995862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
996ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
997f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
998f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
9999ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
1000aff50787SStefano Zampini         PetscInt j,k;
1001aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
1002aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1003aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
100408122e43SStefano Zampini         }
100508122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1006aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1007aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1008aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1009aff50787SStefano Zampini           }
101008122e43SStefano Zampini         }
101108122e43SStefano Zampini       } else {
101208122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
101308122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
101408122e43SStefano Zampini       }
10158bec7fa6SStefano Zampini     } else {
1016f6f667cfSStefano Zampini       S = Sarray + cumarray;
1017f6f667cfSStefano Zampini       St = Starray + cumarray;
10188bec7fa6SStefano Zampini     }
101908122e43SStefano Zampini 
1020aff50787SStefano Zampini     /* see if we can save some work */
1021aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
1022aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1023aff50787SStefano Zampini     }
1024aff50787SStefano Zampini 
1025aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
1026aff50787SStefano Zampini       B_neigs = 0;
1027aff50787SStefano Zampini     } else {
10289ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
102908122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1030f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
10314c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
10329552c7c7SStefano Zampini         PetscInt     nmin_s;
103308122e43SStefano Zampini 
1034fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
10358bec7fa6SStefano 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]]);
1036fd14bc51SStefano Zampini         }
1037d16cbb6bSStefano Zampini 
103808122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1039d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
1040d16cbb6bSStefano Zampini 
1041d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
104208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1043f6f667cfSStefano 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));
104408122e43SStefano Zampini #else
1045f6f667cfSStefano 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));
104608122e43SStefano Zampini #endif
1047d16cbb6bSStefano Zampini         } else {
1048d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1049d16cbb6bSStefano Zampini           B_IL = 1;
1050d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1051d16cbb6bSStefano 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));
1052d16cbb6bSStefano Zampini #else
1053d16cbb6bSStefano 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));
1054d16cbb6bSStefano Zampini #endif
1055d16cbb6bSStefano Zampini         }
105608122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
105708122e43SStefano Zampini         if (B_ierr) {
105808122e43SStefano Zampini           if (B_ierr < 0 ) {
105908122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
106008122e43SStefano Zampini           } else if (B_ierr <= B_N) {
106108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
106208122e43SStefano Zampini           } else {
10639552c7c7SStefano 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);
106408122e43SStefano Zampini           }
106508122e43SStefano Zampini         }
106608122e43SStefano Zampini 
106708122e43SStefano Zampini         if (B_neigs > nmax) {
1068fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1069fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1070fd14bc51SStefano Zampini           }
1071f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
107208122e43SStefano Zampini           B_neigs = nmax;
107308122e43SStefano Zampini         }
107408122e43SStefano Zampini 
10759552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
10769552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
107708122e43SStefano Zampini           PetscBLASInt B_neigs2;
107808122e43SStefano Zampini 
1079f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
1080f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
1081fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1082fd14bc51SStefano 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);
1083fd14bc51SStefano Zampini           }
10849ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
108508122e43SStefano Zampini             PetscInt j;
108608122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
108708122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
108808122e43SStefano Zampini             }
108908122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
109008122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
109108122e43SStefano Zampini             }
109208122e43SStefano Zampini           } else {
109308122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
109408122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
109508122e43SStefano Zampini           }
109608122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
109708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1098f6f667cfSStefano 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));
109908122e43SStefano Zampini #else
1100f6f667cfSStefano 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));
110108122e43SStefano Zampini #endif
110208122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
110308122e43SStefano Zampini           B_neigs += B_neigs2;
110408122e43SStefano Zampini         }
110508122e43SStefano Zampini         if (B_ierr) {
110608122e43SStefano Zampini           if (B_ierr < 0 ) {
110708122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
110808122e43SStefano Zampini           } else if (B_ierr <= B_N) {
110908122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
111008122e43SStefano Zampini           } else {
11119552c7c7SStefano 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);
111208122e43SStefano Zampini           }
111308122e43SStefano Zampini         }
1114fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1115ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
111608122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
111708122e43SStefano Zampini             if (eigs[j] == 0.0) {
1118ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
111908122e43SStefano Zampini             } else {
1120ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
1121fd14bc51SStefano Zampini             }
112208122e43SStefano Zampini           }
112308122e43SStefano Zampini         }
112408122e43SStefano Zampini       } else {
112508122e43SStefano Zampini           /* TODO */
112608122e43SStefano Zampini       }
1127aff50787SStefano Zampini     }
11288bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
11298bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
11309162d606SStefano Zampini     if (B_neigs) {
11319162d606SStefano 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);
1132fd14bc51SStefano Zampini 
1133fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
11349552c7c7SStefano Zampini         PetscInt ii;
11359552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1136ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
11379552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1138ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1139ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1140ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1141ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1142ac47001eSStefano Zampini #else
1143ac47001eSStefano 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);
1144ac47001eSStefano Zampini #endif
11459552c7c7SStefano Zampini           }
11469552c7c7SStefano Zampini         }
1147fd14bc51SStefano Zampini       }
114808122e43SStefano Zampini #if 0
11499162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
115008122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
115108122e43SStefano Zampini         PetscScalar norm;
115208122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
11539162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
11549162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
115508122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
115608122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
115708122e43SStefano Zampini         } else {
115808122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
115908122e43SStefano Zampini         }
11609162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
1161b1b3d7a2SStefano Zampini       }
1162b1b3d7a2SStefano Zampini #endif
11639162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
11649162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
11659162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
11669162d606SStefano Zampini       cum++;
116708122e43SStefano Zampini     }
116808122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
116908122e43SStefano Zampini     /* shift for next computation */
117008122e43SStefano Zampini     cumarray += subset_size*subset_size;
117108122e43SStefano Zampini   }
1172fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1173fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1174fd14bc51SStefano Zampini   }
117508122e43SStefano Zampini 
117608122e43SStefano Zampini   if (mss) {
117708122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
117808122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1179f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1180f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1181f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
118208122e43SStefano Zampini   }
1183f6f667cfSStefano Zampini   if (allocated_S_St) {
1184f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1185f6f667cfSStefano Zampini   }
1186f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
118708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
118808122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
118908122e43SStefano Zampini #endif
119008122e43SStefano Zampini   if (pcbddc->dbg_flag) {
11911b968477SStefano Zampini     PetscInt maxneigs_r;
119208122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
11939b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
119408122e43SStefano Zampini   }
119508122e43SStefano Zampini   PetscFunctionReturn(0);
119608122e43SStefano Zampini }
1197b1b3d7a2SStefano Zampini 
1198674ae819SStefano Zampini #undef __FUNCT__
1199c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1200c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1201c8587f34SStefano Zampini {
1202c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
12038629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1204c8587f34SStefano Zampini   PetscErrorCode ierr;
1205c8587f34SStefano Zampini 
1206c8587f34SStefano Zampini   PetscFunctionBegin;
1207f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
12085e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1209c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1210c8587f34SStefano Zampini 
1211684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
12120fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1213684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1214c8587f34SStefano Zampini 
1215c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1216b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
1217c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1218c8587f34SStefano Zampini   }
1219c8587f34SStefano Zampini 
12208629588bSStefano Zampini   /*
12218629588bSStefano Zampini      Setup local correction and local part of coarse basis.
12228629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
12238629588bSStefano Zampini   */
122447f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
12258629588bSStefano Zampini 
12268629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
12278629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
12288629588bSStefano Zampini 
12298629588bSStefano Zampini   /* free */
12308629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1231c8587f34SStefano Zampini   PetscFunctionReturn(0);
1232c8587f34SStefano Zampini }
1233c8587f34SStefano Zampini 
1234c8587f34SStefano Zampini #undef __FUNCT__
1235674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1236674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1237674ae819SStefano Zampini {
1238674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1239674ae819SStefano Zampini   PetscErrorCode ierr;
1240674ae819SStefano Zampini 
1241674ae819SStefano Zampini   PetscFunctionBegin;
1242674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1243674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
124430368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1245674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
1246674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1247785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1248674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1249f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1250f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1251785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
125263602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
125363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1254674ae819SStefano Zampini   PetscFunctionReturn(0);
1255674ae819SStefano Zampini }
1256674ae819SStefano Zampini 
1257674ae819SStefano Zampini #undef __FUNCT__
1258674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1259674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1260674ae819SStefano Zampini {
1261674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12624f1b2e48SStefano Zampini   PetscInt       i;
1263674ae819SStefano Zampini   PetscErrorCode ierr;
1264674ae819SStefano Zampini 
1265674ae819SStefano Zampini   PetscFunctionBegin;
1266b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1267674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
1268674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1269674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
12704f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
12714f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
12724f1b2e48SStefano Zampini   }
12734f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1274b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1275674ae819SStefano Zampini   PetscFunctionReturn(0);
1276674ae819SStefano Zampini }
1277674ae819SStefano Zampini 
1278674ae819SStefano Zampini #undef __FUNCT__
1279674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1280674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1281674ae819SStefano Zampini {
1282674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1283674ae819SStefano Zampini   PetscErrorCode ierr;
1284674ae819SStefano Zampini 
1285674ae819SStefano Zampini   PetscFunctionBegin;
1286674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
128758da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1288ca92afb2SStefano Zampini     PetscScalar *array;
128906656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
129006656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
129158da7f69SStefano Zampini   }
1292674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1293674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
129415aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
129515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1296674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1297674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1298674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
129906656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1300674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1301674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
13028ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1303674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1304674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1305674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1306f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1307f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1308f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1309f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1310727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
13110e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1312f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
131370cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
13146e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
131581d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
13160369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
13178b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
13184f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
13198b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1320ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1321ca92afb2SStefano Zampini     PetscInt i;
1322ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1323ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1324ca92afb2SStefano Zampini     }
1325ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1326ca92afb2SStefano Zampini   }
13274f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1328674ae819SStefano Zampini   PetscFunctionReturn(0);
1329674ae819SStefano Zampini }
1330674ae819SStefano Zampini 
1331674ae819SStefano Zampini #undef __FUNCT__
1332f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1333f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
13346bfb1811SStefano Zampini {
13356bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
13366bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
13376bfb1811SStefano Zampini   VecType        impVecType;
13384f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
13396bfb1811SStefano Zampini   PetscErrorCode ierr;
13406bfb1811SStefano Zampini 
13416bfb1811SStefano Zampini   PetscFunctionBegin;
1342f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
1343019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1344f4ddd8eeSStefano Zampini   }
1345e7b262bdSStefano Zampini   /* get sizes */
13464f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1347b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
13486bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1349e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1350e7b262bdSStefano Zampini   /* R nodes */
1351e7b262bdSStefano Zampini   old_size = -1;
1352e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1353e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1354e7b262bdSStefano Zampini   }
1355e7b262bdSStefano Zampini   if (n_R != old_size) {
1356e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1357e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
13586bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
13596bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
13606bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
13616bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1362e7b262bdSStefano Zampini   }
1363e7b262bdSStefano Zampini   /* local primal dofs */
1364e7b262bdSStefano Zampini   old_size = -1;
1365e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1366e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1367e7b262bdSStefano Zampini   }
1368e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1369e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
137083b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1371e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
13726bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1373e7b262bdSStefano Zampini   }
1374e7b262bdSStefano Zampini   /* local explicit constraints */
1375e7b262bdSStefano Zampini   old_size = -1;
1376e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1377e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1378e7b262bdSStefano Zampini   }
1379e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1380e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
138183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
138283b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
138383b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
138483b7ccabSStefano Zampini   }
13856bfb1811SStefano Zampini   PetscFunctionReturn(0);
13866bfb1811SStefano Zampini }
13876bfb1811SStefano Zampini 
13886bfb1811SStefano Zampini #undef __FUNCT__
138947f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
139047f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
139188ebb749SStefano Zampini {
139225084f0cSStefano Zampini   PetscErrorCode  ierr;
139325084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
139488ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
139588ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1396d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
139725084f0cSStefano Zampini   /* submatrices of local problem */
139880677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
1399019a44ceSStefano Zampini   /* submatrices of benign trick */
1400d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
140106656605SStefano Zampini   /* submatrices of local coarse problem */
140206656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
140325084f0cSStefano Zampini   /* working matrices */
140406656605SStefano Zampini   Mat             C_CR;
140525084f0cSStefano Zampini   /* additional working stuff */
140606656605SStefano Zampini   PC              pc_R;
14074f1b2e48SStefano Zampini   Mat             F;
1408a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
140906656605SStefano Zampini 
141025084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
141106656605SStefano Zampini   PetscScalar     *work;
141206656605SStefano Zampini   PetscInt        *idx_V_B;
1413ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
141406656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1415ffd830a3SStefano Zampini 
141625084f0cSStefano Zampini   /* some shortcuts to scalars */
141706656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
141888ebb749SStefano Zampini 
141988ebb749SStefano Zampini   PetscFunctionBegin;
1420ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1421ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1422ffd830a3SStefano Zampini   }
1423ffd830a3SStefano Zampini 
1424ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1425b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
14264f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1427b371cd4fSStefano Zampini   n_B = pcis->n_B;
1428b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
142988ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
143088ebb749SStefano Zampini 
143188ebb749SStefano Zampini   /* vertices in boundary numbering */
1432785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
14330e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
143488ebb749SStefano Zampini   if (i != n_vertices) {
143522d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
143688ebb749SStefano Zampini   }
143788ebb749SStefano Zampini 
143806656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1439019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
144006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
144106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
144206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
144306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
144406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
144506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
144606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
144706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
144806656605SStefano Zampini 
144906656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
145006656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
145106656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
145206656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
145306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1454ffd830a3SStefano Zampini   lda_rhs = n_R;
1455a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
145606656605SStefano Zampini   if (isLU || isILU || isCHOL) {
145706656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1458df4d28bfSStefano Zampini   } else if (sub_schurs->reuse_solver) {
1459df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1460d62866d3SStefano Zampini     MatFactorType      type;
1461d62866d3SStefano Zampini 
1462df4d28bfSStefano Zampini     F = reuse_solver->F;
14636816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1464d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1465ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
1466df4d28bfSStefano Zampini     need_benign_correction = !!reuse_solver->benign_n;
146706656605SStefano Zampini   } else {
146806656605SStefano Zampini     F = NULL;
146906656605SStefano Zampini   }
147006656605SStefano Zampini 
1471ffd830a3SStefano Zampini   /* allocate workspace */
1472ffd830a3SStefano Zampini   n = 0;
1473ffd830a3SStefano Zampini   if (n_constraints) {
1474ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1475ffd830a3SStefano Zampini   }
1476ffd830a3SStefano Zampini   if (n_vertices) {
1477ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1478ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1479ffd830a3SStefano Zampini   }
1480ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1481ffd830a3SStefano Zampini 
148288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
148388ebb749SStefano Zampini   if (n_constraints) {
148406656605SStefano Zampini     Mat         M1,M2,M3;
148580677318SStefano Zampini     Mat         auxmat;
148606656605SStefano Zampini     IS          is_aux;
148780677318SStefano Zampini     PetscScalar *array,*array2;
148806656605SStefano Zampini 
1489f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
149080677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
149188ebb749SStefano Zampini 
149225084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
149325084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
14948ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
149580677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
149688ebb749SStefano Zampini 
149780677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
149880677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1499ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
150088ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
150106656605SStefano Zampini       const PetscScalar *row_cmat_values;
150206656605SStefano Zampini       const PetscInt    *row_cmat_indices;
150306656605SStefano Zampini       PetscInt          size_of_constraint,j;
150488ebb749SStefano Zampini 
150506656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
150606656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1507ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
150806656605SStefano Zampini       }
150906656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
151006656605SStefano Zampini     }
1511ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
151206656605SStefano Zampini     if (F) {
151306656605SStefano Zampini       Mat B;
151406656605SStefano Zampini 
1515ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1516a3df083aSStefano Zampini       if (need_benign_correction) {
1517a3df083aSStefano Zampini         PetscScalar        *marr;
1518df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1519a3df083aSStefano Zampini 
1520a3df083aSStefano Zampini         ierr = MatDenseGetArray(B,&marr);CHKERRQ(ierr);
1521a3df083aSStefano Zampini         for (i=0;i<n_constraints;i++) {
1522a3df083aSStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1523df4d28bfSStefano Zampini           ierr = PCBDDCReuseSolversChangeInterior(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE);CHKERRQ(ierr);
1524a3df083aSStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1525a3df083aSStefano Zampini         }
1526a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(B,&marr);CHKERRQ(ierr);
1527a3df083aSStefano Zampini       }
152880677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1529a3df083aSStefano Zampini       if (need_benign_correction) {
1530a3df083aSStefano Zampini         PetscScalar        *marr;
1531df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1532a3df083aSStefano Zampini 
1533a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1534a3df083aSStefano Zampini         for (i=0;i<n_constraints;i++) {
1535a3df083aSStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1536df4d28bfSStefano Zampini           ierr = PCBDDCReuseSolversChangeInterior(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE);CHKERRQ(ierr);
1537a3df083aSStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1538a3df083aSStefano Zampini         }
1539a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1540a3df083aSStefano Zampini       }
154106656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
154206656605SStefano Zampini     } else {
154380677318SStefano Zampini       PetscScalar *marr;
154480677318SStefano Zampini 
154580677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
154606656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1547ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1548ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
154906656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
155006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
155106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
155206656605SStefano Zampini       }
155380677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
155406656605SStefano Zampini     }
155580677318SStefano Zampini     if (!pcbddc->switch_static) {
155680677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
155780677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
155880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
155980677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1560ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
156180677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
156280677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
156380677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
156480677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
156580677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
156680677318SStefano Zampini       }
156780677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
156880677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
156980677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
157080677318SStefano Zampini     } else {
1571ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1572ffd830a3SStefano Zampini         IS dummy;
1573ffd830a3SStefano Zampini 
1574ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
1575ffd830a3SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,dummy,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1576ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1577ffd830a3SStefano Zampini       } else {
157880677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
157980677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1580ffd830a3SStefano Zampini       }
158125084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
158280677318SStefano Zampini     }
158380677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
158480677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
158580677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
158606656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
158706656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
158880677318SStefano Zampini     if (isCHOL) {
158980677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
159080677318SStefano Zampini     } else {
159125084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
159280677318SStefano Zampini     }
159380677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
159406656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
159525084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
159625084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
159725084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
159880677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
159980677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
160080677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
160106656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
160206656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1603f4ddd8eeSStefano Zampini   }
160488ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
16054f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
1606d16cbb6bSStefano Zampini     IS        dummy;
1607d16cbb6bSStefano Zampini     Mat       B0_R;
1608d16cbb6bSStefano Zampini     PetscReal norm;
1609d16cbb6bSStefano Zampini 
16104f1b2e48SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
16114f1b2e48SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
1612d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
1613d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
1614d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
1615d16cbb6bSStefano Zampini     }
1616d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
1617d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1618d16cbb6bSStefano Zampini   }
1619d16cbb6bSStefano Zampini 
162088ebb749SStefano Zampini   if (n_vertices) {
162106656605SStefano Zampini     IS is_aux;
16223a50541eSStefano Zampini 
1623df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
16246816873aSStefano Zampini       IS tis;
16256816873aSStefano Zampini 
16266816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
16276816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
16286816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
16296816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
16306816873aSStefano Zampini     } else {
16313a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
16326816873aSStefano Zampini     }
16339577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
16349577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
163504708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
16364f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1637019a44ceSStefano Zampini       IS dummy;
1638019a44ceSStefano Zampini 
16394f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
16404f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1641019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1642019a44ceSStefano Zampini     }
164325084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
164488ebb749SStefano Zampini   }
164588ebb749SStefano Zampini 
164688ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1647f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
164806656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
164906656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
165006656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
165106656605SStefano Zampini     }
1652f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
165306656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
165406656605SStefano Zampini       PetscScalar *marray;
165506656605SStefano Zampini 
165606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
165706656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1658f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1659f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1660f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1661f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1662f4ddd8eeSStefano Zampini     }
1663f4ddd8eeSStefano Zampini   }
166406656605SStefano Zampini 
1665f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
166606656605SStefano Zampini     PetscScalar *marray;
166788ebb749SStefano Zampini 
166806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
16698eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
167006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
167188ebb749SStefano Zampini     }
16723301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
167306656605SStefano Zampini       n *= 2;
167488ebb749SStefano Zampini     }
167506656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
167606656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
167706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
16788eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
167906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
168006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
168188ebb749SStefano Zampini     }
16823301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
168306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
16848eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
168506656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
168606656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
168788ebb749SStefano Zampini       }
168888ebb749SStefano Zampini     } else {
1689c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1690c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
16911b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1692c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1693c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1694c0553b1fSStefano Zampini       }
169588ebb749SStefano Zampini     }
169606656605SStefano Zampini   }
1697019a44ceSStefano Zampini 
169806656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
16994f1b2e48SStefano Zampini   p0_lidx_I = NULL;
17004f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1701d12edf2fSStefano Zampini     const PetscInt *idxs;
1702d12edf2fSStefano Zampini 
1703d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
17044f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
17054f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
17064f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
17074f1b2e48SStefano Zampini     }
1708d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1709d12edf2fSStefano Zampini   }
1710d16cbb6bSStefano Zampini 
171106656605SStefano Zampini   /* vertices */
171206656605SStefano Zampini   if (n_vertices) {
171316f15bc4SStefano Zampini 
1714ffd830a3SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
171504708bb6SStefano Zampini 
171616f15bc4SStefano Zampini     if (n_R) {
171714393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
171806656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
171916f15bc4SStefano Zampini       PetscScalar  *x,*y;
172004708bb6SStefano Zampini       PetscBool    isseqaij;
172106656605SStefano Zampini 
172221eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
172314393ed6SStefano Zampini       if (need_benign_correction) {
172414393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
172514393ed6SStefano Zampini         IS                     is_p0;
172614393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
172714393ed6SStefano Zampini 
172814393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
172914393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
173014393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
173114393ed6SStefano Zampini         if (n != pcbddc->benign_n) {
173214393ed6SStefano Zampini           SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %d != %d\n",n,pcbddc->benign_n);
173314393ed6SStefano Zampini         }
173414393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
173514393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
173614393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
173714393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
173814393ed6SStefano Zampini       }
173914393ed6SStefano Zampini 
1740ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
1741ffd830a3SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
1742ffd830a3SStefano Zampini       } else {
1743ca92afb2SStefano Zampini         PetscScalar    *av,*array;
1744ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
1745ca92afb2SStefano Zampini         PetscInt       n;
1746ca92afb2SStefano Zampini         PetscBool      flg_row;
1747ffd830a3SStefano Zampini 
1748ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
1749ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
1750ca92afb2SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
1751ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1752ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
1753ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
1754ca92afb2SStefano Zampini           PetscInt j;
1755ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
1756ffd830a3SStefano Zampini         }
1757ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1758ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1759ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
1760ffd830a3SStefano Zampini       }
1761ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
176214393ed6SStefano Zampini       if (F) {
1763a3df083aSStefano Zampini         if (need_benign_correction) {
1764df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1765a3df083aSStefano Zampini           PetscScalar        *marr;
1766a3df083aSStefano Zampini 
1767a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
176814393ed6SStefano Zampini           /* need \Phi^T A_RV = (I+L)A_RV, L given by
176914393ed6SStefano Zampini 
177014393ed6SStefano Zampini                  | 0 0  0 | (V)
177114393ed6SStefano Zampini              L = | 0 0 -1 | (P-p0)
177214393ed6SStefano Zampini                  | 0 0 -1 | (p0)
177314393ed6SStefano Zampini 
177414393ed6SStefano Zampini           */
1775df4d28bfSStefano Zampini           for (i=0;i<reuse_solver->benign_n;i++) {
177614393ed6SStefano Zampini             const PetscScalar *vals;
177714393ed6SStefano Zampini             const PetscInt    *idxs,*idxs_zero;
177814393ed6SStefano Zampini             PetscInt          n,j,nz;
177914393ed6SStefano Zampini 
1780df4d28bfSStefano Zampini             ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1781df4d28bfSStefano Zampini             ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
178214393ed6SStefano Zampini             ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
178314393ed6SStefano Zampini             for (j=0;j<n;j++) {
178414393ed6SStefano Zampini               PetscScalar val = vals[j];
178514393ed6SStefano Zampini               PetscInt    k,col = idxs[j];
178614393ed6SStefano Zampini               for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
178714393ed6SStefano Zampini             }
178814393ed6SStefano Zampini             ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
1789df4d28bfSStefano Zampini             ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
179014393ed6SStefano Zampini           }
179114393ed6SStefano Zampini           /* need to correct the rhs */
1792a3df083aSStefano Zampini           for (i=0;i<n_vertices;i++) {
1793a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1794df4d28bfSStefano Zampini             ierr = PCBDDCReuseSolversChangeInterior(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE);CHKERRQ(ierr);
1795a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1796a3df083aSStefano Zampini           }
1797a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
1798a3df083aSStefano Zampini         }
179906656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
180014393ed6SStefano Zampini         /* need to correct the solution */
1801a3df083aSStefano Zampini         if (need_benign_correction) {
1802df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1803a3df083aSStefano Zampini           PetscScalar        *marr;
1804a3df083aSStefano Zampini 
1805a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
1806a3df083aSStefano Zampini           for (i=0;i<n_vertices;i++) {
1807a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
1808df4d28bfSStefano Zampini             ierr = PCBDDCReuseSolversChangeInterior(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE);CHKERRQ(ierr);
1809a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1810a3df083aSStefano Zampini           }
1811a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
1812a3df083aSStefano Zampini         }
181306656605SStefano Zampini       } else {
181406656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
181506656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
1816ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
1817ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
181806656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
181906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
182006656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
182106656605SStefano Zampini         }
182206656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
182306656605SStefano Zampini       }
182480677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1825ffd830a3SStefano Zampini       /* S_VV and S_CV */
182606656605SStefano Zampini       if (n_constraints) {
182706656605SStefano Zampini         Mat B;
182880677318SStefano Zampini 
1829ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
183080677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
1831ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1832ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
183380677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183480677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183580677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
183680677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
183780677318SStefano Zampini         }
1838ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
183980677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
184080677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
1841ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
184280677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
184306656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
1844ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
1845ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
184606656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
184706656605SStefano Zampini       }
184804708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
184904708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
185004708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
185104708bb6SStefano Zampini       }
1852ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1853ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
1854ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
1855ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
1856ffd830a3SStefano Zampini       }
185706656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
185814393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
185914393ed6SStefano Zampini       if (need_benign_correction) {
1860df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
186114393ed6SStefano Zampini         PetscScalar      *marr,*sums;
186214393ed6SStefano Zampini 
186314393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
186414393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
1865df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
186614393ed6SStefano Zampini           const PetscScalar *vals;
186714393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
186814393ed6SStefano Zampini           PetscInt          n,j,nz;
186914393ed6SStefano Zampini 
1870df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1871df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
187214393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
187314393ed6SStefano Zampini             PetscInt k;
187414393ed6SStefano Zampini             sums[j] = 0.;
187514393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
187614393ed6SStefano Zampini           }
187714393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
187814393ed6SStefano Zampini           for (j=0;j<n;j++) {
187914393ed6SStefano Zampini             PetscScalar val = vals[j];
188014393ed6SStefano Zampini             PetscInt k;
188114393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
188214393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
188314393ed6SStefano Zampini             }
188414393ed6SStefano Zampini           }
188514393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
1886df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
188714393ed6SStefano Zampini         }
188814393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
188914393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
189014393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
189114393ed6SStefano Zampini       }
189280677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
189306656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
189406656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
189506656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
189606656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
189706656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
189806656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
189906656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1900d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1901019a44ceSStefano Zampini     } else {
1902d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1903d16cbb6bSStefano Zampini     }
19044f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1905019a44ceSStefano Zampini       const PetscScalar *vals;
1906019a44ceSStefano Zampini       const PetscInt    *idxs;
19074f1b2e48SStefano Zampini       PetscInt          n,j,primal_idx;
1908019a44ceSStefano Zampini 
19094f1b2e48SStefano Zampini       ierr = MatGetRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
19104f1b2e48SStefano Zampini       primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + i;
1911d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
19124f1b2e48SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+idxs[j]] = vals[j];
19134f1b2e48SStefano Zampini         coarse_submat_vals[idxs[j]*pcbddc->local_primal_size+primal_idx] = vals[j];
1914019a44ceSStefano Zampini       }
19154f1b2e48SStefano Zampini       ierr = MatRestoreRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
191616f15bc4SStefano Zampini     }
191721eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1918d16cbb6bSStefano Zampini 
191906656605SStefano Zampini     /* coarse basis functions */
192006656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
192116f15bc4SStefano Zampini       PetscScalar *y;
192216f15bc4SStefano Zampini 
1923ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
192406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
192506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
192606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
192706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
192806656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
192906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
193006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
193106656605SStefano Zampini 
193206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
19334f1b2e48SStefano Zampini         PetscInt j;
19344f1b2e48SStefano Zampini 
193506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
193606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
193706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
193806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
193906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
19404f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
194106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
194206656605SStefano Zampini       }
194306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
194406656605SStefano Zampini     }
194504708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
194604708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
194706656605SStefano Zampini   }
194806656605SStefano Zampini 
194906656605SStefano Zampini   if (n_constraints) {
195006656605SStefano Zampini     Mat B;
195106656605SStefano Zampini 
1952ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
195306656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
195480677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
195506656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
195606656605SStefano Zampini     if (n_vertices) {
195780677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
195880677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
195980677318SStefano Zampini       } else {
196080677318SStefano Zampini         Mat S_VCt;
196180677318SStefano Zampini 
1962ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
1963ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
1964ffd830a3SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B);CHKERRQ(ierr);
1965ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
1966ffd830a3SStefano Zampini         }
196780677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
196880677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
196980677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
197080677318SStefano Zampini       }
197106656605SStefano Zampini     }
197206656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
197306656605SStefano Zampini     /* coarse basis functions */
197406656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
197506656605SStefano Zampini       PetscScalar *y;
197606656605SStefano Zampini 
1977ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
197806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
197906656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
198006656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
198106656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
198206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
198306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
198406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
19854f1b2e48SStefano Zampini         PetscInt j;
19864f1b2e48SStefano Zampini 
198706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
198806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
198906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
19924f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
199306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
199406656605SStefano Zampini       }
199506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
199606656605SStefano Zampini     }
199706656605SStefano Zampini   }
199880677318SStefano Zampini   if (n_constraints) {
199980677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
200080677318SStefano Zampini   }
20014f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
2002019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
2003019a44ceSStefano Zampini 
200406656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
20053301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
2006ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
2007ffd830a3SStefano Zampini     PetscScalar *marray;
200806656605SStefano Zampini 
200906656605SStefano Zampini     if (n_constraints) {
2010ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
201106656605SStefano Zampini 
2012ffd830a3SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
201306656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
2014ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
201516f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
201606656605SStefano Zampini       if (n_vertices) {
2017ffd830a3SStefano Zampini         Mat S_VCT;
201806656605SStefano Zampini 
201906656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
2020ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
202116f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
202206656605SStefano Zampini       }
2023ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
202406656605SStefano Zampini     }
202516f15bc4SStefano Zampini     if (n_vertices && n_R) {
2026ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2027ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2028ffd830a3SStefano Zampini       PetscInt       n;
2029ffd830a3SStefano Zampini       PetscBool      flg_row;
203006656605SStefano Zampini 
2031ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2032ffd830a3SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
2033ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2034ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2035ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2036ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2037ffd830a3SStefano Zampini         PetscInt j;
2038ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2039ffd830a3SStefano Zampini       }
2040ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2041ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2042ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
204306656605SStefano Zampini     }
204406656605SStefano Zampini 
2045ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2046ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2047ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2048ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2049ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
205006656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
205106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
205206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
205306656605SStefano Zampini     }
2054ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2055ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2056ffd830a3SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2057ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2058ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2059ffd830a3SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2060ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2061ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
206206656605SStefano Zampini     }
2063ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
206406656605SStefano Zampini     /* coarse basis functions */
206506656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
206606656605SStefano Zampini       PetscScalar *y;
206706656605SStefano Zampini 
2068ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
206906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
207006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
207106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
207206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
207306656605SStefano Zampini       if (i<n_vertices) {
207406656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
207506656605SStefano Zampini       }
207606656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
207706656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
207806656605SStefano Zampini 
207906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
208006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
208106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
208206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
208306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
208406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
208506656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
208606656605SStefano Zampini       }
208706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
208806656605SStefano Zampini     }
2089ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2090ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
209106656605SStefano Zampini   }
2092d62866d3SStefano Zampini   /* free memory */
209388ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
209406656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
209506656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
209606656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
209706656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2098d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2099d62866d3SStefano Zampini   if (n_vertices) {
2100d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2101d62866d3SStefano Zampini   }
2102d62866d3SStefano Zampini   if (n_constraints) {
2103d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2104d62866d3SStefano Zampini   }
210588ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
210688ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
210788ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2108d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
210988ebb749SStefano Zampini     Mat         coarse_sub_mat;
211025084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
211188ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
211288ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
211388ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
21148bec7fa6SStefano Zampini     Mat         C_B,CPHI;
21158bec7fa6SStefano Zampini     IS          is_dummy;
21168bec7fa6SStefano Zampini     Vec         mones;
211788ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
211888ebb749SStefano Zampini     PetscReal   real_value;
211988ebb749SStefano Zampini 
2120a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2121a3df083aSStefano Zampini       Mat A;
2122a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2123a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2124a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2125a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2126a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2127a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2128a3df083aSStefano Zampini     } else {
212988ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
213088ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
213188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
213288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2133a3df083aSStefano Zampini     }
213488ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
213588ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2136ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
213788ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
213888ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
213988ebb749SStefano Zampini     }
214088ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
214188ebb749SStefano Zampini 
214225084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
21433301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
214425084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2145ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
214688ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
214788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
214888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
214988ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
215088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
215188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
215288ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
215388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
215488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
215588ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
215688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
215788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
215888ebb749SStefano Zampini     } else {
215988ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
216088ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
216188ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
216288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
216388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
216488ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
216588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
216688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
216788ebb749SStefano Zampini     }
216888ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
216988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
217088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
217188ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
21724f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2173d12edf2fSStefano Zampini       Mat         B0_I,B0_B,B0_BPHI,B0_IPHI;
2174d12edf2fSStefano Zampini       PetscScalar *data,*data2;
21754f1b2e48SStefano Zampini       PetscInt    j;
2176d12edf2fSStefano Zampini 
21774f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
21784f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
21794f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
2180d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
2181d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2182d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2183d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
21844f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
21854f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2186d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
21874f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
21884f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
21894f1b2e48SStefano Zampini         }
2190d12edf2fSStefano Zampini       }
2191d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2192d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2193d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2194d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2195d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2196d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
2197d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
2198d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2199d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
2200d12edf2fSStefano Zampini     }
2201d12edf2fSStefano Zampini #if 0
2202d12edf2fSStefano Zampini   {
2203d12edf2fSStefano Zampini     PetscViewer viewer;
2204d12edf2fSStefano Zampini     char filename[256];
2205ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2206d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2207d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2208ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2209ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2210ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2211d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
2212ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2213ffd830a3SStefano Zampini     ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
2214ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2215ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2216ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2217ffd830a3SStefano Zampini     }
2218ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2219ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2220ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2221ffd830a3SStefano Zampini     }
2222ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_B) {
2223ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2224ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2225ffd830a3SStefano Zampini     }
2226d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2227d12edf2fSStefano Zampini   }
2228d12edf2fSStefano Zampini #endif
222981d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
22308bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
22311575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
223206656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
22338bec7fa6SStefano Zampini 
22348bec7fa6SStefano Zampini     /* check constraints */
22354f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
22368bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
22378bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
22388bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
22398bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
22408bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
22418bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
22428bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2243bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2244ffd830a3SStefano Zampini       if (!pcbddc->symmetric_primal) {
2245bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2246bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2247bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2248bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2249bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
225088ebb749SStefano Zampini       }
22518bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
22528bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
22538bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
22548bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
2255d12edf2fSStefano Zampini     }
225625084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
225788ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
225888ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
225988ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
226088ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
226188ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
226288ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
226388ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
226488ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
226588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
226688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2267ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
226888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
226988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
227088ebb749SStefano Zampini     }
227188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
227288ebb749SStefano Zampini   }
22738629588bSStefano Zampini   /* get back data */
22748629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
227588ebb749SStefano Zampini   PetscFunctionReturn(0);
227688ebb749SStefano Zampini }
227788ebb749SStefano Zampini 
227888ebb749SStefano Zampini #undef __FUNCT__
2279d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2280d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2281aa0d41d4SStefano Zampini {
2282d65f70fdSStefano Zampini   Mat            *work_mat;
2283d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2284d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2285d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
2286aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2287aa0d41d4SStefano Zampini 
2288aa0d41d4SStefano Zampini   PetscFunctionBegin;
2289d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2290d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2291d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2292d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2293aa0d41d4SStefano Zampini 
2294d65f70fdSStefano Zampini   if (!rsorted) {
2295906d46d4SStefano Zampini     const PetscInt *idxs;
2296906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2297aa0d41d4SStefano Zampini 
2298d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2299d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2300d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2301d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2302aa0d41d4SStefano Zampini     }
2303d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2304d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2305d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2306d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2307aa0d41d4SStefano Zampini     }
2308d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2309d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2310d65f70fdSStefano Zampini   } else {
2311d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2312d65f70fdSStefano Zampini     isrow_s = isrow;
2313aa0d41d4SStefano Zampini   }
2314906d46d4SStefano Zampini 
2315d65f70fdSStefano Zampini   if (!csorted) {
2316d65f70fdSStefano Zampini     if (isrow == iscol) {
2317d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2318d65f70fdSStefano Zampini       iscol_s = isrow_s;
2319d65f70fdSStefano Zampini     } else {
2320d65f70fdSStefano Zampini       const PetscInt *idxs;
2321d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
2322906d46d4SStefano Zampini 
2323d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2324d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2325d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2326d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2327d65f70fdSStefano Zampini       }
2328d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2329d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2330d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2331d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2332d65f70fdSStefano Zampini       }
2333d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2334d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2335d65f70fdSStefano Zampini     }
2336d65f70fdSStefano Zampini   } else {
2337d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2338d65f70fdSStefano Zampini     iscol_s = iscol;
2339d65f70fdSStefano Zampini   }
2340d65f70fdSStefano Zampini 
2341d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2342d65f70fdSStefano Zampini 
2343d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2344906d46d4SStefano Zampini     Mat      new_mat;
2345d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2346906d46d4SStefano Zampini 
2347d65f70fdSStefano Zampini     if (!rsorted) {
2348d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2349d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2350d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2351d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2352906d46d4SStefano Zampini       }
2353d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2354d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2355d65f70fdSStefano Zampini     } else {
2356d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2357906d46d4SStefano Zampini     }
2358d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2359d65f70fdSStefano Zampini 
2360d65f70fdSStefano Zampini     if (!csorted) {
2361d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2362d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2363d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2364d65f70fdSStefano Zampini       } else {
2365d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2366d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2367d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2368d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2369d65f70fdSStefano Zampini         }
2370d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2371d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2372d65f70fdSStefano Zampini       }
2373d65f70fdSStefano Zampini     } else {
2374d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2375d65f70fdSStefano Zampini     }
2376d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2377d65f70fdSStefano Zampini 
2378d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2379d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2380d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2381d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2382d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2383d65f70fdSStefano Zampini   }
2384d65f70fdSStefano Zampini 
2385d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2386d65f70fdSStefano Zampini   *B = work_mat[0];
2387d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2388d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2389d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2390d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2391d65f70fdSStefano Zampini }
2392d65f70fdSStefano Zampini 
2393d65f70fdSStefano Zampini #undef __FUNCT__
23945e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
23955e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2396aa0d41d4SStefano Zampini {
2397aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
23985e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2399d65f70fdSStefano Zampini   Mat            new_mat;
24005e8657edSStefano Zampini   IS             is_local,is_global;
2401d65f70fdSStefano Zampini   PetscInt       local_size;
2402d65f70fdSStefano Zampini   PetscBool      isseqaij;
2403aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2404aa0d41d4SStefano Zampini 
2405aa0d41d4SStefano Zampini   PetscFunctionBegin;
2406aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
24075e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
24085e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2409b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2410aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2411d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2412aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2413906d46d4SStefano Zampini 
2414906d46d4SStefano Zampini   /* check */
2415906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2416906d46d4SStefano Zampini     Vec       x,x_change;
2417906d46d4SStefano Zampini     PetscReal error;
2418906d46d4SStefano Zampini 
24195e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2420906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
24215e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2422e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2423e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2424d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2425e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2426e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2427906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2428906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2429906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2430906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2431906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2432906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2433906d46d4SStefano Zampini   }
2434906d46d4SStefano Zampini 
243522d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
24369b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
243722d5777bSStefano Zampini   if (isseqaij) {
24381cf9b237SStefano Zampini     Mat M;
24391cf9b237SStefano Zampini 
24401cf9b237SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
24411cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
24421cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2443aa0d41d4SStefano Zampini   } else {
24441cf9b237SStefano Zampini     Mat work_mat,M;
24451cf9b237SStefano Zampini 
2446aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
24471cf9b237SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
24481cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
24491cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2450aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2451aa0d41d4SStefano Zampini   }
24523301b35fSStefano Zampini   if (matis->A->symmetric_set) {
24533301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2454e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
24553301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2456e496cd5dSStefano Zampini #endif
24573301b35fSStefano Zampini   }
245845a1bb75SStefano Zampini   /*
245945a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2460d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
246145a1bb75SStefano Zampini   */
2462d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2463aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2464aa0d41d4SStefano Zampini }
2465aa0d41d4SStefano Zampini 
2466aa0d41d4SStefano Zampini #undef __FUNCT__
2467a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
24688ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2469a64d13efSStefano Zampini {
2470a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2471a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2472d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
247353892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
24743a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
24753a50541eSStefano Zampini   PetscInt        vbs,bs;
24766816873aSStefano Zampini   PetscBT         bitmask=NULL;
2477a64d13efSStefano Zampini   PetscErrorCode  ierr;
2478a64d13efSStefano Zampini 
2479a64d13efSStefano Zampini   PetscFunctionBegin;
2480b23d619eSStefano Zampini   /*
2481b23d619eSStefano Zampini     No need to setup local scatters if
2482b23d619eSStefano Zampini       - primal space is unchanged
2483b23d619eSStefano Zampini         AND
2484b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2485b23d619eSStefano Zampini         AND
2486b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2487b23d619eSStefano Zampini   */
2488b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2489f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2490f4ddd8eeSStefano Zampini   }
2491f4ddd8eeSStefano Zampini   /* destroy old objects */
2492f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2493f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2494f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2495a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2496b371cd4fSStefano Zampini   n_B = pcis->n_B;
2497b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2498b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
24993a50541eSStefano Zampini 
2500a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
25016816873aSStefano Zampini 
250253892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2503df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
2504854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2505a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2506a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
25070e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2508a64d13efSStefano Zampini     }
2509a64d13efSStefano Zampini 
2510a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
25114641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
25126816873aSStefano Zampini         idx_R_local[n_R++] = i;
2513a64d13efSStefano Zampini       }
2514a64d13efSStefano Zampini     }
2515df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2516df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
25176816873aSStefano Zampini 
2518df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2519df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
25206816873aSStefano Zampini   }
25213a50541eSStefano Zampini 
25223a50541eSStefano Zampini   /* Block code */
25233a50541eSStefano Zampini   vbs = 1;
25243a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
25253a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
25263a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
25273a50541eSStefano Zampini     PetscInt  *vary;
2528df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
2529785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
25303a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2531d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2532d3df7717SStefano 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 */
25330e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2534d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
25353a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
25363a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
25373a50541eSStefano Zampini           break;
25383a50541eSStefano Zampini         }
25393a50541eSStefano Zampini       }
2540d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2541d3df7717SStefano Zampini     } else {
2542d3df7717SStefano Zampini       /* Verify directly the R set */
2543d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2544d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2545d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2546d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2547d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2548d3df7717SStefano Zampini             break;
2549d3df7717SStefano Zampini           }
2550d3df7717SStefano Zampini         }
2551d3df7717SStefano Zampini       }
2552d3df7717SStefano Zampini     }
25533a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
25543a50541eSStefano Zampini       vbs = bs;
25553a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
25563a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
25573a50541eSStefano Zampini       }
25583a50541eSStefano Zampini     }
25593a50541eSStefano Zampini   }
25603a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2561df4d28bfSStefano Zampini   if (sub_schurs->reuse_solver) {
2562df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
256353892102SStefano Zampini 
2564df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2565df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
256653892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2567df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
256853892102SStefano Zampini   } else {
25693a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
257053892102SStefano Zampini   }
2571a64d13efSStefano Zampini 
2572a64d13efSStefano Zampini   /* print some info if requested */
2573a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2574a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2575a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
25761575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2577a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2578a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
25794f1b2e48SStefano 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);
2580a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2581a64d13efSStefano Zampini   }
2582a64d13efSStefano Zampini 
2583a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
2584df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
25856816873aSStefano Zampini     IS       is_aux1,is_aux2;
25866816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
25876816873aSStefano Zampini 
25883a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2589854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2590854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2591a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
25924641a718SStefano Zampini     for (i=0; i<n_D; i++) {
25934641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
25944641a718SStefano Zampini     }
2595a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2596a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
25974641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
25984641a718SStefano Zampini         aux_array1[j++] = i;
2599a64d13efSStefano Zampini       }
2600a64d13efSStefano Zampini     }
2601a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2602a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2603a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
26044641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
26054641a718SStefano Zampini         aux_array2[j++] = i;
2606a64d13efSStefano Zampini       }
2607a64d13efSStefano Zampini     }
2608a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2609a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2610a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2611a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2612a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2613a64d13efSStefano Zampini 
26148eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2615785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2616a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
26174641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
26184641a718SStefano Zampini           aux_array1[j++] = i;
2619a64d13efSStefano Zampini         }
2620a64d13efSStefano Zampini       }
2621a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2622a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2623a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2624a64d13efSStefano Zampini     }
26254641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
26263a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2627d62866d3SStefano Zampini   } else {
2628df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
26296816873aSStefano Zampini     IS                 tis;
26306816873aSStefano Zampini     PetscInt           schur_size;
26316816873aSStefano Zampini 
2632df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
26336816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
2634df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
26356816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
26366816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
26376816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
26386816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
26396816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2640d62866d3SStefano Zampini     }
2641d62866d3SStefano Zampini   }
2642a64d13efSStefano Zampini   PetscFunctionReturn(0);
2643a64d13efSStefano Zampini }
2644a64d13efSStefano Zampini 
2645304d26faSStefano Zampini 
2646304d26faSStefano Zampini #undef __FUNCT__
2647304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2648684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2649304d26faSStefano Zampini {
2650304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2651304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2652304d26faSStefano Zampini   PC             pc_temp;
2653304d26faSStefano Zampini   Mat            A_RR;
2654f4ddd8eeSStefano Zampini   MatReuse       reuse;
2655304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2656304d26faSStefano Zampini   PetscReal      value;
265704708bb6SStefano Zampini   PetscInt       n_D,n_R;
26589577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
2659304d26faSStefano Zampini   PetscErrorCode ierr;
2660e604994aSStefano Zampini   /* prefixes stuff */
2661312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2662e604994aSStefano Zampini   size_t         len;
2663304d26faSStefano Zampini 
2664304d26faSStefano Zampini   PetscFunctionBegin;
2665304d26faSStefano Zampini 
2666e604994aSStefano Zampini   /* compute prefixes */
2667e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2668e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2669e604994aSStefano Zampini   if (!pcbddc->current_level) {
2670e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2671e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2672e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2673e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2674e604994aSStefano Zampini   } else {
2675e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2676312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2677e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2678e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2679312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2680312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
268134d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
268234d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2683e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2684e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2685e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
2686e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
2687e604994aSStefano Zampini   }
2688e604994aSStefano Zampini 
2689304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
2690684f6988SStefano Zampini   if (dirichlet) {
2691d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2692a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit && pcbddc->dbg_flag) {
2693a3df083aSStefano Zampini       Mat    A_IIn;
2694a3df083aSStefano Zampini 
2695a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
2696a3df083aSStefano Zampini       ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
2697a3df083aSStefano Zampini       pcis->A_II = A_IIn;
2698a3df083aSStefano Zampini     }
26993301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
27003301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2701964fefecSStefano Zampini     }
2702ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
2703964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
2704304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
2705304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
2706304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
2707304d26faSStefano Zampini       /* default */
2708304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
2709e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
27109577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2711304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
27129577ea80SStefano Zampini       if (issbaij) {
27139577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
27149577ea80SStefano Zampini       } else {
2715304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
27169577ea80SStefano Zampini       }
2717304d26faSStefano Zampini       /* Allow user's customization */
2718304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
2719304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2720304d26faSStefano Zampini     }
2721d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
2722df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
2723df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2724d62866d3SStefano Zampini 
2725df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
2726d5574798SStefano Zampini     }
2727304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2728304d26faSStefano Zampini     if (!n_D) {
2729304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
2730304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2731304d26faSStefano Zampini     }
2732304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
2733304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
2734304d26faSStefano Zampini     /* set ksp_D into pcis data */
2735304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
2736304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
2737304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
2738684f6988SStefano Zampini   }
2739304d26faSStefano Zampini 
2740304d26faSStefano Zampini   /* NEUMANN PROBLEM */
2741684f6988SStefano Zampini   A_RR = 0;
2742684f6988SStefano Zampini   if (neumann) {
2743d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
274404708bb6SStefano Zampini     PetscInt        ibs,mbs;
274504708bb6SStefano Zampini     PetscBool       issbaij;
274604708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
2747f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
27488ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
2749f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
2750f4ddd8eeSStefano Zampini       PetscInt nn_R;
275181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
2752f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2753f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
2754f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
2755f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
2756f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2757f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2758f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
2759727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
2760f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2761f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
2762f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
2763f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
2764f4ddd8eeSStefano Zampini         }
2765f4ddd8eeSStefano Zampini       }
2766f4ddd8eeSStefano Zampini       /* last check */
2767d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
2768f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2769f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2770f4ddd8eeSStefano Zampini       }
2771f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
2772f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
2773f4ddd8eeSStefano Zampini     }
2774f4ddd8eeSStefano Zampini     /* extract A_RR */
2775af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
2776af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
277704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
277804708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
277904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
278004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
278104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2782af732b37SStefano Zampini       } else {
278304708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
27846816873aSStefano Zampini       }
278504708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
278604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
278704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
278804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
278904708bb6SStefano Zampini       } else {
279004708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
279104708bb6SStefano Zampini       }
279204708bb6SStefano Zampini     }
2793f4ddd8eeSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
27943301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
27953301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
27966816873aSStefano Zampini     }
2797a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit && pcbddc->dbg_flag) {
2798a3df083aSStefano Zampini       Mat A_RRn;
2799a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RRn);CHKERRQ(ierr);
2800a3df083aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2801a3df083aSStefano Zampini       A_RR = A_RRn;
2802a3df083aSStefano Zampini     }
2803f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
2804304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
2805304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
2806304d26faSStefano Zampini       /* default */
2807304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
2808e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
2809304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
28109577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
28119577ea80SStefano Zampini       if (issbaij) {
28129577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
28139577ea80SStefano Zampini       } else {
2814304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
28159577ea80SStefano Zampini       }
2816304d26faSStefano Zampini       /* Allow user's customization */
2817304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
2818304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2819304d26faSStefano Zampini     }
2820304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2821304d26faSStefano Zampini     if (!n_R) {
2822304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2823304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2824304d26faSStefano Zampini     }
2825df4d28bfSStefano Zampini     /* Reuse solver if it is present */
2826df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
2827df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2828d62866d3SStefano Zampini 
2829df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
2830d62866d3SStefano Zampini     }
2831ffd830a3SStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2832304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
2833304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2834684f6988SStefano Zampini   }
28356816873aSStefano Zampini   /* free Neumann problem's matrix */
28366816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2837304d26faSStefano Zampini 
2838304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
28390fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2840684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
2841684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
28421575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2843684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2844684f6988SStefano Zampini     }
2845684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
28460fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
28470fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
28480fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
28490fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
28500fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2851304d26faSStefano Zampini       /* need to be adapted? */
2852b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2853b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2854b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2855304d26faSStefano Zampini       /* print info */
2856304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2857e604994aSStefano 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);
2858304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2859304d26faSStefano Zampini       }
2860b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2861298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2862304d26faSStefano Zampini       }
2863684f6988SStefano Zampini     }
2864684f6988SStefano Zampini     if (neumann) { /* Neumann */
28656816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
28660fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
28670fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
28680fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
28690fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
28700fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2871304d26faSStefano Zampini       /* need to be adapted? */
2872b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2873b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2874304d26faSStefano Zampini       /* print info */
2875304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2876e604994aSStefano 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);
2877304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2878304d26faSStefano Zampini       }
2879b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2880298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2881304d26faSStefano Zampini       }
28820fccc4e9SStefano Zampini     }
2883684f6988SStefano Zampini   }
2884304d26faSStefano Zampini   PetscFunctionReturn(0);
2885304d26faSStefano Zampini }
2886304d26faSStefano Zampini 
2887304d26faSStefano Zampini #undef __FUNCT__
2888ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
288980677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2890674ae819SStefano Zampini {
2891674ae819SStefano Zampini   PetscErrorCode  ierr;
2892674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2893be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2894674ae819SStefano Zampini 
2895674ae819SStefano Zampini   PetscFunctionBegin;
2896df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
289780677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
289820c7b377SStefano Zampini   }
289980677318SStefano Zampini   if (!pcbddc->switch_static) {
290080677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
290180677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
290280677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
290320c7b377SStefano Zampini     }
2904df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
290580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
290680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
290720c7b377SStefano Zampini     } else {
2908df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2909be83ff47SStefano Zampini 
2910df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2911df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
291220c7b377SStefano Zampini     }
2913be83ff47SStefano Zampini   } else {
291480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
291880677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
291980677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
292080677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
292180677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
292280677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2923674ae819SStefano Zampini     }
2924674ae819SStefano Zampini   }
2925df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
292680677318SStefano Zampini     if (applytranspose) {
292780677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
292880677318SStefano Zampini     } else {
292980677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
293080677318SStefano Zampini     }
2931be83ff47SStefano Zampini   } else {
2932df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2933be83ff47SStefano Zampini 
2934be83ff47SStefano Zampini     if (applytranspose) {
2935df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
2936be83ff47SStefano Zampini     } else {
2937df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
2938be83ff47SStefano Zampini     }
2939be83ff47SStefano Zampini   }
294080677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
294180677318SStefano Zampini   if (!pcbddc->switch_static) {
2942df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
294380677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
294480677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2945be83ff47SStefano Zampini     } else {
2946df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2947be83ff47SStefano Zampini 
2948df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2949df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2950be83ff47SStefano Zampini     }
295180677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
295280677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
295380677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
295480677318SStefano Zampini     }
295580677318SStefano Zampini   } else {
295680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
295780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
295880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
295980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296080677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
296180677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
296280677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
296380677318SStefano Zampini     }
296480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2968674ae819SStefano Zampini   }
2969674ae819SStefano Zampini   PetscFunctionReturn(0);
2970674ae819SStefano Zampini }
2971674ae819SStefano Zampini 
2972dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2973674ae819SStefano Zampini #undef __FUNCT__
2974674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2975dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2976674ae819SStefano Zampini {
2977674ae819SStefano Zampini   PetscErrorCode ierr;
2978674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2979674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2980674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2981674ae819SStefano Zampini 
2982674ae819SStefano Zampini   PetscFunctionBegin;
2983dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2984dc359a40SStefano Zampini   if (applytranspose) {
2985674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
29868eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2987dc359a40SStefano Zampini   } else {
2988674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2989674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
299015aaf578SStefano Zampini   }
2991efc2fbd9SStefano Zampini 
2992efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
29934f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2994efc2fbd9SStefano Zampini     PetscScalar *array;
29954f1b2e48SStefano Zampini     PetscInt    j;
2996efc2fbd9SStefano Zampini 
2997efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
29984f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
2999efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3000efc2fbd9SStefano Zampini   }
3001efc2fbd9SStefano Zampini 
300212edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
300312edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
300412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
300512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
300612edc857SStefano Zampini 
30079f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
300812edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
300912edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
301051694757SStefano Zampini     Mat coarse_mat;
3011964fefecSStefano Zampini     Vec rhs,sol;
301251694757SStefano Zampini     MatNullSpace nullsp;
3013964fefecSStefano Zampini 
3014964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3015964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
301651694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
301751694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
301851694757SStefano Zampini     if (nullsp) {
301951694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
302051694757SStefano Zampini     }
302112edc857SStefano Zampini     if (applytranspose) {
3022964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
302312edc857SStefano Zampini     } else {
3024964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
302512edc857SStefano Zampini     }
302651694757SStefano Zampini     if (nullsp) {
302751694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
302851694757SStefano Zampini     }
302912edc857SStefano Zampini   }
3030674ae819SStefano Zampini 
3031674ae819SStefano Zampini   /* Local solution on R nodes */
303280677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
303380677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
30349f00e9b4SStefano Zampini   }
3035674ae819SStefano Zampini 
30369f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
30379f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
303812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3039674ae819SStefano Zampini 
3040674ae819SStefano Zampini   /* Sum contributions from two levels */
3041dc359a40SStefano Zampini   if (applytranspose) {
3042dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3043dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3044dc359a40SStefano Zampini   } else {
3045674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
30468eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3047dc359a40SStefano Zampini   }
3048efc2fbd9SStefano Zampini   /* store p0 */
30494f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
3050efc2fbd9SStefano Zampini     PetscScalar *array;
30514f1b2e48SStefano Zampini     PetscInt    j;
3052efc2fbd9SStefano Zampini 
3053efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
30544f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3055efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3056efc2fbd9SStefano Zampini   }
3057674ae819SStefano Zampini   PetscFunctionReturn(0);
3058674ae819SStefano Zampini }
3059674ae819SStefano Zampini 
3060674ae819SStefano Zampini #undef __FUNCT__
3061674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
306212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3063674ae819SStefano Zampini {
3064674ae819SStefano Zampini   PetscErrorCode ierr;
3065674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
306658da7f69SStefano Zampini   PetscScalar    *array;
306712edc857SStefano Zampini   Vec            from,to;
3068674ae819SStefano Zampini 
3069674ae819SStefano Zampini   PetscFunctionBegin;
307012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
307112edc857SStefano Zampini     from = pcbddc->coarse_vec;
307212edc857SStefano Zampini     to = pcbddc->vec1_P;
307312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
307412edc857SStefano Zampini       Vec tvec;
307558da7f69SStefano Zampini 
307658da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
307758da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
307812edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
307958da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
308058da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
308158da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
308212edc857SStefano Zampini     }
308312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
308412edc857SStefano Zampini     from = pcbddc->vec1_P;
308512edc857SStefano Zampini     to = pcbddc->coarse_vec;
308612edc857SStefano Zampini   }
308712edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3088674ae819SStefano Zampini   PetscFunctionReturn(0);
3089674ae819SStefano Zampini }
3090674ae819SStefano Zampini 
3091674ae819SStefano Zampini #undef __FUNCT__
3092674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
309312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3094674ae819SStefano Zampini {
3095674ae819SStefano Zampini   PetscErrorCode ierr;
3096674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
309758da7f69SStefano Zampini   PetscScalar    *array;
309812edc857SStefano Zampini   Vec            from,to;
3099674ae819SStefano Zampini 
3100674ae819SStefano Zampini   PetscFunctionBegin;
310112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
310212edc857SStefano Zampini     from = pcbddc->coarse_vec;
310312edc857SStefano Zampini     to = pcbddc->vec1_P;
310412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
310512edc857SStefano Zampini     from = pcbddc->vec1_P;
310612edc857SStefano Zampini     to = pcbddc->coarse_vec;
310712edc857SStefano Zampini   }
310812edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
310912edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
311012edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
311112edc857SStefano Zampini       Vec tvec;
311258da7f69SStefano Zampini 
311312edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
311458da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
311558da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
311658da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
311758da7f69SStefano Zampini     }
311858da7f69SStefano Zampini   } else {
311958da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
312058da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
312112edc857SStefano Zampini     }
312212edc857SStefano Zampini   }
3123674ae819SStefano Zampini   PetscFunctionReturn(0);
3124674ae819SStefano Zampini }
3125674ae819SStefano Zampini 
3126984c4197SStefano Zampini /* uncomment for testing purposes */
3127984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3128674ae819SStefano Zampini #undef __FUNCT__
3129674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3130674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3131674ae819SStefano Zampini {
3132674ae819SStefano Zampini   PetscErrorCode    ierr;
3133674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3134674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3135674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3136984c4197SStefano Zampini   /* one and zero */
3137984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3138984c4197SStefano Zampini   /* space to store constraints and their local indices */
31399162d606SStefano Zampini   PetscScalar       *constraints_data;
31409162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
31419162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
31429162d606SStefano Zampini   PetscInt          *constraints_n;
3143984c4197SStefano Zampini   /* iterators */
3144b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3145984c4197SStefano Zampini   /* BLAS integers */
3146e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3147e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3148c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3149727cdba6SStefano Zampini   /* reuse */
31500e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
31510e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3152984c4197SStefano Zampini   /* change of basis */
3153b3d85658SStefano Zampini   PetscBool         qr_needed;
31549162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3155984c4197SStefano Zampini   /* auxiliary stuff */
315664efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
31578a0068c3SStefano Zampini   PetscInt          ncc;
3158984c4197SStefano Zampini   /* some quantities */
315945a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3160a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3161984c4197SStefano Zampini 
3162674ae819SStefano Zampini   PetscFunctionBegin;
31638e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
31648e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
31658e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3166088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3167088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
31680e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
31690e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
31700e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
31710e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
31720e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3173088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3174cf5a6209SStefano Zampini 
3175cf5a6209SStefano Zampini   /* print some info */
3176cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
3177cf5a6209SStefano Zampini     IS       vertices;
3178cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
3179cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
3180cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
3181cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
31821575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3183cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3184cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3185fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
3186fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
3187cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
31881575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3189cf5a6209SStefano Zampini   }
3190cf5a6209SStefano Zampini 
3191cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
31929162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3193cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3194cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3195cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3196cf5a6209SStefano Zampini     PetscScalar  *array;
3197cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3198cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3199674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3200b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3201674ae819SStefano Zampini     PetscScalar  *work;
3202674ae819SStefano Zampini     PetscReal    *singular_vals;
3203674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3204674ae819SStefano Zampini     PetscReal    *rwork;
3205674ae819SStefano Zampini #endif
3206674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3207674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3208674ae819SStefano Zampini #else
3209964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3210964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3211674ae819SStefano Zampini #endif
3212674ae819SStefano Zampini 
3213674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3214d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3215d06fc5fdSStefano Zampini     /* free unneeded index sets */
3216d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3217d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3218674ae819SStefano Zampini     }
3219d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3220d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3221d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3222d06fc5fdSStefano Zampini       }
3223d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3224d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3225d06fc5fdSStefano Zampini     }
3226d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3227d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3228d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3229d06fc5fdSStefano Zampini       }
3230d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3231d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3232d06fc5fdSStefano Zampini     }
323370022509SStefano Zampini 
323470022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
323570022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
323670022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
323770022509SStefano Zampini     if (pcbddc->NullSpace) {
323870022509SStefano Zampini       PetscBool tbool[2],gbool[2];
323970022509SStefano Zampini 
324070022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
3241b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
3242d06fc5fdSStefano Zampini         if (!ISForEdges) {
3243d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
3244d06fc5fdSStefano Zampini         }
3245b8ffe317SStefano Zampini       }
3246d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
3247d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
3248d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3249d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
3250d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
325198a51de6SStefano Zampini     }
325270022509SStefano Zampini #endif
325308122e43SStefano Zampini 
3254674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3255674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3256674ae819SStefano Zampini     if (nearnullsp) {
3257674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3258f4ddd8eeSStefano Zampini       /* remove any stored info */
3259f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3260f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3261f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3262f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3263f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3264473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3265f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3266f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3267f4ddd8eeSStefano Zampini       }
3268984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3269984c4197SStefano Zampini       nnsp_size = 0;
3270674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3271674ae819SStefano Zampini     }
3272984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3273984c4197SStefano Zampini     max_constraints = nnsp_size;
3274984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3275984c4197SStefano Zampini 
3276674ae819SStefano Zampini     /*
3277674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
32789162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
32799162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
32809162d606SStefano Zampini          There can be multiple constraints per connected component
3281674ae819SStefano Zampini                                                                                                                                                            */
3282674ae819SStefano Zampini     n_vertices = 0;
3283674ae819SStefano Zampini     if (ISForVertices) {
3284674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3285674ae819SStefano Zampini     }
32869162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
32879162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
32889162d606SStefano Zampini 
32899162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
32909162d606SStefano Zampini     total_counts *= max_constraints;
3291674ae819SStefano Zampini     total_counts += n_vertices;
32924641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
32939162d606SStefano Zampini 
3294674ae819SStefano Zampini     total_counts = 0;
3295674ae819SStefano Zampini     max_size_of_constraint = 0;
3296674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
32979162d606SStefano Zampini       IS used_is;
3298674ae819SStefano Zampini       if (i<n_ISForEdges) {
32999162d606SStefano Zampini         used_is = ISForEdges[i];
3300674ae819SStefano Zampini       } else {
33019162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3302674ae819SStefano Zampini       }
33039162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3304674ae819SStefano Zampini       total_counts += j;
3305674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3306674ae819SStefano Zampini     }
33079162d606SStefano 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);
33089162d606SStefano Zampini 
3309984c4197SStefano Zampini     /* get local part of global near null space vectors */
3310785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3311984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3312984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3313e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3314e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3315984c4197SStefano Zampini     }
3316674ae819SStefano Zampini 
3317242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3318242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3319a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3320242a89d7SStefano Zampini 
3321984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3322a773dcb8SStefano Zampini     if (!skip_lapack) {
3323674ae819SStefano Zampini       PetscScalar temp_work;
3324911cabfeSStefano Zampini 
3325674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3326984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3327785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3328785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3329785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3330674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3331785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3332674ae819SStefano Zampini #endif
3333674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3334c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3335c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3336674ae819SStefano Zampini       lwork = -1;
3337674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3338674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3339c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3340674ae819SStefano Zampini #else
3341c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3342674ae819SStefano Zampini #endif
3343674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3344984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3345674ae819SStefano Zampini #else /* on missing GESVD */
3346674ae819SStefano Zampini       /* SVD */
3347674ae819SStefano Zampini       PetscInt max_n,min_n;
3348674ae819SStefano Zampini       max_n = max_size_of_constraint;
3349984c4197SStefano Zampini       min_n = max_constraints;
3350984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3351674ae819SStefano Zampini         min_n = max_size_of_constraint;
3352984c4197SStefano Zampini         max_n = max_constraints;
3353674ae819SStefano Zampini       }
3354785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3355674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3356785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3357674ae819SStefano Zampini #endif
3358674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3359674ae819SStefano Zampini       lwork = -1;
3360e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3361e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3362b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3363674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3364674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
33659162d606SStefano 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));
3366674ae819SStefano Zampini #else
33679162d606SStefano 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));
3368674ae819SStefano Zampini #endif
3369674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3370984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3371984c4197SStefano Zampini #endif /* on missing GESVD */
3372674ae819SStefano Zampini       /* Allocate optimal workspace */
3373674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3374854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3375674ae819SStefano Zampini     }
3376674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3377674ae819SStefano Zampini     total_counts = 0;
33789162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
33799162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3380674ae819SStefano Zampini     /* vertices */
33819162d606SStefano Zampini     if (n_vertices) {
3382674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
33839162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3384674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
33859162d606SStefano Zampini         constraints_n[total_counts] = 1;
33869162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
33879162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
33889162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3389674ae819SStefano Zampini         total_counts++;
3390674ae819SStefano Zampini       }
3391674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3392674ae819SStefano Zampini       n_vertices = total_counts;
3393674ae819SStefano Zampini     }
3394984c4197SStefano Zampini 
3395674ae819SStefano Zampini     /* edges and faces */
33969162d606SStefano Zampini     total_counts_cc = total_counts;
3397911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
33989162d606SStefano Zampini       IS        used_is;
33999162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
34009162d606SStefano Zampini 
3401911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
34029162d606SStefano Zampini         used_is = ISForEdges[ncc];
3403984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3404674ae819SStefano Zampini       } else {
34059162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3406984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3407674ae819SStefano Zampini       }
3408674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
34099162d606SStefano Zampini 
34109162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
34119162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3412984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3413984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3414674ae819SStefano Zampini       if (nnsp_has_cnst) {
34155b08dc53SStefano Zampini         PetscScalar quad_value;
34169162d606SStefano Zampini 
34179162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
34189162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
34199162d606SStefano Zampini 
3420a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3421674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3422a773dcb8SStefano Zampini         } else {
3423a773dcb8SStefano Zampini           quad_value = 1.0;
3424a773dcb8SStefano Zampini         }
3425674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
34269162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3427674ae819SStefano Zampini         }
34289162d606SStefano Zampini         temp_constraints++;
3429674ae819SStefano Zampini         total_counts++;
3430674ae819SStefano Zampini       }
3431674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3432984c4197SStefano Zampini         PetscReal real_value;
34339162d606SStefano Zampini         PetscScalar *ptr_to_data;
34349162d606SStefano Zampini 
3435984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
34369162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3437674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
34389162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3439674ae819SStefano Zampini         }
3440984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3441984c4197SStefano Zampini         /* check if array is null on the connected component */
3442e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
34439162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
34445b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3445674ae819SStefano Zampini           temp_constraints++;
3446674ae819SStefano Zampini           total_counts++;
34479162d606SStefano Zampini           if (!idxs_copied) {
34489162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
34499162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3450674ae819SStefano Zampini           }
3451674ae819SStefano Zampini         }
34529162d606SStefano Zampini       }
34539162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
345445a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3455eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3456a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
34579162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
34589162d606SStefano Zampini 
34599162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3460a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
34619162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3462a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
34639162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3464a773dcb8SStefano Zampini         } else { /* perform SVD */
3465984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
34669162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3467674ae819SStefano Zampini 
3468674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3469984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3470984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3471984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3472984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3473984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3474984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3475984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3476984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3477674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3478e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3479984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3480674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3481674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
34829162d606SStefano 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));
3483674ae819SStefano Zampini             }
3484674ae819SStefano Zampini           }
3485e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3486e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3487e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3488674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3489c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3490674ae819SStefano Zampini #else
3491c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3492674ae819SStefano Zampini #endif
3493674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3494984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3495984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3496674ae819SStefano Zampini           j = 0;
3497984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3498674ae819SStefano Zampini           total_counts = total_counts-j;
349945a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3500e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3501c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3502c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3503c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3504c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3505c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3506c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3507674ae819SStefano Zampini           if (j<temp_constraints) {
3508984c4197SStefano Zampini             PetscInt ii;
3509984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3510674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
35119162d606SStefano 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));
3512674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3513984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3514674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
35159162d606SStefano 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];
3516674ae819SStefano Zampini               }
3517674ae819SStefano Zampini             }
3518674ae819SStefano Zampini           }
3519674ae819SStefano Zampini #else  /* on missing GESVD */
3520e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3521e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3522b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3523674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3524674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
35259162d606SStefano 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));
3526674ae819SStefano Zampini #else
35279162d606SStefano 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));
3528674ae819SStefano Zampini #endif
3529984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3530674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3531984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3532e310c8b4SStefano Zampini           k = temp_constraints;
3533e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3534674ae819SStefano Zampini           j = 0;
3535e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
353645a1bb75SStefano Zampini           valid_constraints = k-j;
3537911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3538984c4197SStefano Zampini #endif /* on missing GESVD */
3539674ae819SStefano Zampini         }
3540a773dcb8SStefano Zampini       }
35419162d606SStefano Zampini       /* update pointers information */
35429162d606SStefano Zampini       if (valid_constraints) {
35439162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
35449162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
35459162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
35469162d606SStefano Zampini         /* set change_of_basis flag */
354745a1bb75SStefano Zampini         if (boolforchange) {
3548b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
35499162d606SStefano Zampini         }
3550b3d85658SStefano Zampini         total_counts_cc++;
355145a1bb75SStefano Zampini       }
355245a1bb75SStefano Zampini     }
3553984c4197SStefano Zampini     /* free workspace */
35548f1c130eSStefano Zampini     if (!skip_lapack) {
3555984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3556984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3557984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3558984c4197SStefano Zampini #endif
3559984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3560984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3561984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3562984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3563984c4197SStefano Zampini #endif
3564984c4197SStefano Zampini     }
3565984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3566984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3567984c4197SStefano Zampini     }
3568984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3569cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3570cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3571cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3572cf5a6209SStefano Zampini     }
3573cf5a6209SStefano Zampini     if (n_ISForFaces) {
3574cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3575cf5a6209SStefano Zampini     }
3576cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3577cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3578cf5a6209SStefano Zampini     }
3579cf5a6209SStefano Zampini     if (n_ISForEdges) {
3580cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3581cf5a6209SStefano Zampini     }
3582cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
358308122e43SStefano Zampini   } else {
358408122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3585984c4197SStefano Zampini 
358608122e43SStefano Zampini     total_counts = 0;
358708122e43SStefano Zampini     n_vertices = 0;
3588d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3589d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
359008122e43SStefano Zampini     }
359108122e43SStefano Zampini     max_constraints = 0;
35929162d606SStefano Zampini     total_counts_cc = 0;
359308122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
359408122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
35959162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
359608122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
359708122e43SStefano Zampini     }
35989162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
35999162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
36009162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
36019162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
360274d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
36039162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
36049162d606SStefano Zampini     total_counts_cc = 0;
36059162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
36069162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
36079162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
360808122e43SStefano Zampini       }
360908122e43SStefano Zampini     }
36109162d606SStefano Zampini #if 0
36119162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
36129162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
36139162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
36149162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
36159162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
36169162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
36179162d606SStefano Zampini       }
36189162d606SStefano Zampini       printf("\n");
36199162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
36209162d606SStefano Zampini     }
36211b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
36228bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
36231b968477SStefano Zampini     }
36241b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
36258bec7fa6SStefano 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]);
36261b968477SStefano Zampini     }
362708122e43SStefano Zampini #endif
362808122e43SStefano Zampini 
36298bec7fa6SStefano Zampini     max_size_of_constraint = 0;
36309162d606SStefano 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]);
36319162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
363208122e43SStefano Zampini     /* Change of basis */
3633b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
363408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
363508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
363608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3637b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
363808122e43SStefano Zampini         }
363908122e43SStefano Zampini       }
364008122e43SStefano Zampini     }
364108122e43SStefano Zampini   }
3642984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
36434f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
364408122e43SStefano Zampini 
36459162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
36469162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
36479162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
36489162d606SStefano 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);
364908122e43SStefano Zampini   }
3650674ae819SStefano Zampini 
3651674ae819SStefano Zampini   /* Create constraint matrix */
3652674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
365316f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
3654984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
3655984c4197SStefano Zampini 
3656984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
3657a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
3658a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
365974d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
3660984c4197SStefano Zampini   total_primal_vertices=0;
3661b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
36629162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
36639162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3664984c4197SStefano Zampini     if (size_of_constraint == 1) {
36659162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
3666b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
366764efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
36689162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
36699162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
3670a717540cSStefano Zampini       }
3671b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
367274d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
3673a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
3674a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
3675a717540cSStefano Zampini       }
3676fa434743SStefano Zampini     } else {
3677b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
3678fa434743SStefano Zampini     }
3679a717540cSStefano Zampini   }
3680b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
3681b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
3682674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
368370022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3684b3d85658SStefano Zampini 
36854f1b2e48SStefano 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);
36860e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
36870e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
3688984c4197SStefano Zampini 
3689984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
369074d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
3691785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
3692984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
369374d5cdf7SStefano Zampini 
3694984c4197SStefano Zampini   j = total_primal_vertices;
369574d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
3696b3d85658SStefano Zampini   cum = total_primal_vertices;
36979162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
36984641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
3699b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
3700b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
3701b3d85658SStefano Zampini       cum++;
37029162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
370374d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
370474d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
370574d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
370674d5cdf7SStefano Zampini       }
37079162d606SStefano Zampini       j += constraints_n[i];
3708674ae819SStefano Zampini     }
3709674ae819SStefano Zampini   }
3710674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
3711674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
3712088faed8SStefano Zampini 
3713674ae819SStefano Zampini   /* set values in constraint matrix */
3714984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
37150e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3716674ae819SStefano Zampini   }
3717984c4197SStefano Zampini   total_counts = total_primal_vertices;
37189162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
37194641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
37209162d606SStefano Zampini       PetscInt *cols;
37219162d606SStefano Zampini 
37229162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
37239162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
37249162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
37259162d606SStefano Zampini         PetscInt    row = total_counts+k;
37269162d606SStefano Zampini         PetscScalar *vals;
37279162d606SStefano Zampini 
37289162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
37299162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
37309162d606SStefano Zampini       }
37319162d606SStefano Zampini       total_counts += constraints_n[i];
3732674ae819SStefano Zampini     }
3733674ae819SStefano Zampini   }
3734674ae819SStefano Zampini   /* assembling */
3735674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3736674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3737088faed8SStefano Zampini 
3738984c4197SStefano Zampini   /*
373945a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3740984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
3741984c4197SStefano Zampini   */
3742674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
3743674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
3744026de310SStefano Zampini     /* dual and primal dofs on a single cc */
3745984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
3746984c4197SStefano Zampini     /* working stuff for GEQRF */
374781d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
3748984c4197SStefano Zampini     PetscBLASInt lqr_work;
3749984c4197SStefano Zampini     /* working stuff for UNGQR */
3750984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
3751984c4197SStefano Zampini     PetscBLASInt lgqr_work;
3752984c4197SStefano Zampini     /* working stuff for TRTRS */
3753984c4197SStefano Zampini     PetscScalar  *trs_rhs;
37543f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
3755984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
3756984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
3757984c4197SStefano Zampini     PetscScalar  *start_vals;
3758984c4197SStefano Zampini     /* working stuff for values insertion */
37594641a718SStefano Zampini     PetscBT      is_primal;
376064efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
3761906d46d4SStefano Zampini     /* matrix sizes */
3762906d46d4SStefano Zampini     PetscInt     global_size,local_size;
3763906d46d4SStefano Zampini     /* temporary change of basis */
3764906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
3765cf5a6209SStefano Zampini     /* extra space for debugging */
3766cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
3767984c4197SStefano Zampini 
3768906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
3769906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
377016f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
3771bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3772906d46d4SStefano Zampini     /* nonzeros for local mat */
3773bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
3774bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
37759162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
3776a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
37779162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3778a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
37799162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
3780a717540cSStefano Zampini         } else {
37819162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
37829162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
3783a717540cSStefano Zampini         }
3784a717540cSStefano Zampini       }
3785a717540cSStefano Zampini     }
3786906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
3787bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3788a717540cSStefano Zampini     /* Set initial identity in the matrix */
3789bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
3790906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3791a717540cSStefano Zampini     }
3792a717540cSStefano Zampini 
3793a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
3794a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3795a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3796a717540cSStefano Zampini     }
3797a717540cSStefano Zampini 
3798a717540cSStefano Zampini 
3799a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
3800a717540cSStefano Zampini     /*
3801a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3802a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3803a717540cSStefano Zampini 
3804a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
3805a717540cSStefano Zampini 
3806a6b551f4SStefano 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)
3807a6b551f4SStefano Zampini 
3808a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
3809a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
3810a717540cSStefano Zampini             |              ...                        |
3811a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
3812a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3813a717540cSStefano Zampini 
3814a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
3815a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3816a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3817a6b551f4SStefano Zampini 
3818a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
3819a717540cSStefano Zampini     */
3820a717540cSStefano Zampini     if (qr_needed) {
3821984c4197SStefano Zampini       /* space to store Q */
3822854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3823984c4197SStefano Zampini       /* first we issue queries for optimal work */
38243f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
38253f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
38263f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3827984c4197SStefano Zampini       lqr_work = -1;
38283f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3829984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3830984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3831785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3832984c4197SStefano Zampini       lgqr_work = -1;
38333f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
38343f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
38353f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
38363f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
38373f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
38383f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3839984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3840984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3841785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3842984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3843785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3844984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3845785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3846a717540cSStefano Zampini       /* allocating workspace for check */
3847a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3848cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3849a717540cSStefano Zampini       }
3850a717540cSStefano Zampini     }
3851984c4197SStefano Zampini     /* array to store whether a node is primal or not */
38524641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3853473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
38540e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
385539e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
385639e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
38574641a718SStefano Zampini     }
385839e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
385939e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
386039e2fb2aSStefano Zampini     }
386139e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3862984c4197SStefano Zampini 
3863a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
38649162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
38659162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
38664641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3867984c4197SStefano Zampini         /* get constraint info */
38689162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3869984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3870984c4197SStefano Zampini 
3871984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
38729162d606SStefano 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);
3873674ae819SStefano Zampini         }
3874984c4197SStefano Zampini 
3875fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3876a717540cSStefano Zampini 
3877a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3878a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
38799162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3880a717540cSStefano Zampini           }
3881984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
38829162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3883984c4197SStefano Zampini 
3884984c4197SStefano Zampini           /* compute QR decomposition of constraints */
38853f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
38863f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
38873f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3888674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38893f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3890984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3891674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3892984c4197SStefano Zampini 
3893984c4197SStefano Zampini           /* explictly compute R^-T */
3894984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3895984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
38963f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
38973f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
38983f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
38993f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3900984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
39013f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3902984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3903984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3904984c4197SStefano Zampini 
3905a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
39063f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
39073f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39083f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
39093f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3910984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
39113f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3912984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3913984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3914984c4197SStefano Zampini 
3915984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3916984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3917984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
39183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
39193f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
39203f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
39213f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
39223f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
39233f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3924984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
39259162d606SStefano 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));
3926984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
39279162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3928984c4197SStefano Zampini 
3929984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
39309162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3931984c4197SStefano Zampini           /* insert cols for primal dofs */
3932984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3933984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
39349162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3935906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3936984c4197SStefano Zampini           }
3937984c4197SStefano Zampini           /* insert cols for dual dofs */
3938984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
39399162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3940984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
39419162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3942906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3943984c4197SStefano Zampini               j++;
3944674ae819SStefano Zampini             }
3945674ae819SStefano Zampini           }
3946984c4197SStefano Zampini 
3947984c4197SStefano Zampini           /* check change of basis */
3948984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3949984c4197SStefano Zampini             PetscInt   ii,jj;
3950984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3951c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3952c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3953c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3954c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3955c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3956c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3957984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3958cf5a6209SStefano 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));
3959984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3960984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3961984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3962cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3963cf5a6209SStefano 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;
3964674ae819SStefano Zampini               }
3965674ae819SStefano Zampini             }
3966984c4197SStefano Zampini             if (!valid_qr) {
396722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3968984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3969984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3970cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3971cf5a6209SStefano 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]));
3972674ae819SStefano Zampini                   }
3973cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3974cf5a6209SStefano 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]));
3975984c4197SStefano Zampini                   }
3976984c4197SStefano Zampini                 }
3977984c4197SStefano Zampini               }
3978674ae819SStefano Zampini             } else {
397922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3980674ae819SStefano Zampini             }
3981674ae819SStefano Zampini           }
3982a717540cSStefano Zampini         } else { /* simple transformation block */
3983a717540cSStefano Zampini           PetscInt    row,col;
3984a6b551f4SStefano Zampini           PetscScalar val,norm;
3985a6b551f4SStefano Zampini 
3986a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39879162d606SStefano 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));
3988a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
39899162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
39909162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3991bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
39929162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3993906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
39949162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3995a717540cSStefano Zampini             } else {
3996a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
39979162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3998a717540cSStefano Zampini                 if (row != col) {
39999162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
4000a717540cSStefano Zampini                 } else {
40019162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
4002a717540cSStefano Zampini                 }
4003906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
4004a717540cSStefano Zampini               }
4005a717540cSStefano Zampini             }
4006a717540cSStefano Zampini           }
400798a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
400822d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4009a717540cSStefano Zampini           }
4010674ae819SStefano Zampini         }
4011984c4197SStefano Zampini       } else {
4012984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
40139162d606SStefano 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);
4014674ae819SStefano Zampini         }
4015674ae819SStefano Zampini       }
4016674ae819SStefano Zampini     }
4017a717540cSStefano Zampini 
4018a717540cSStefano Zampini     /* free workspace */
4019a717540cSStefano Zampini     if (qr_needed) {
4020984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4021cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4022984c4197SStefano Zampini       }
4023984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4024984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4025984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4026984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4027984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4028674ae819SStefano Zampini     }
4029a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4030906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4031906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4032906d46d4SStefano Zampini 
4033906d46d4SStefano Zampini     /* assembling of global change of variable */
4034bbb9e6c6SStefano Zampini     {
4035bbb9e6c6SStefano Zampini       Mat      tmat;
403616f15bc4SStefano Zampini       PetscInt bs;
403716f15bc4SStefano Zampini 
4038906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4039906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4040bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4041bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4042bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4043bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
404416f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
404516f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4046906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4047bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4048bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4049bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4050bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4051bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4052e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4053e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4054bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4055bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
4056906d46d4SStefano Zampini     }
4057906d46d4SStefano Zampini     /* check */
4058906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
4059906d46d4SStefano Zampini       PetscReal error;
4060906d46d4SStefano Zampini       Vec       x,x_change;
4061906d46d4SStefano Zampini 
4062906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4063906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4064906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4065906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4066e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4067e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4068bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4069e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4070e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4071906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4072906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4073906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4074906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4075bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4076906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
4077906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4078906d46d4SStefano Zampini     }
4079b96c3477SStefano Zampini 
4080b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
4081b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
4082b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4083b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
4084ac632422SStefano Zampini         Mat                    S_new,tmat;
4085b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
4086b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
4087b087196eSStefano Zampini         const PetscScalar      *array;
4088b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
4089b087196eSStefano Zampini         PetscInt               i,n_V;
4090bbb9e6c6SStefano Zampini 
4091bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
40926816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4093b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4094b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4095b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4096b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4097bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4098b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4099ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4100b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4101ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4102b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4103b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4104b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4105b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4106b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4107b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
4108b087196eSStefano Zampini           PetscScalar val;
4109b087196eSStefano Zampini           PetscInt    idx;
4110b087196eSStefano Zampini 
4111b087196eSStefano Zampini           idx = idxs_V[i];
4112b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
4113b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4114b087196eSStefano Zampini         }
4115b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4116b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4117ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
4118ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4119ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
4120ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4121b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4122ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4123b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4124ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
4125ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4126ac632422SStefano Zampini         }
4127b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4128b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4129b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4130b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4131b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
4132b96c3477SStefano Zampini       }
4133b96c3477SStefano Zampini     }
4134906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
4135906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
4136b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4137b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4138b9b85e73SStefano Zampini   }
4139906d46d4SStefano Zampini 
4140906d46d4SStefano Zampini   /* set up change of basis context */
4141906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
4142906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
4143906d46d4SStefano Zampini 
4144906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
4145906d46d4SStefano Zampini       PetscInt global_size,local_size;
4146906d46d4SStefano Zampini 
4147906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4148906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4149906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
4150906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4151906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
4152906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
4153906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
4154906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
4155906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
4156906d46d4SStefano Zampini     } else {
4157906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
4158906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
4159906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
4160906d46d4SStefano Zampini     }
4161906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
4162906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4163906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
4164906d46d4SStefano Zampini     } else {
4165906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4166906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
4167906d46d4SStefano Zampini     }
4168906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
4169906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
4170906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4171906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4172a8661815SStefano Zampini   } else {
4173a8661815SStefano Zampini     ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr);
4174b9b85e73SStefano Zampini   }
4175a717540cSStefano Zampini 
41764f1b2e48SStefano Zampini   /* add pressure dofs to set of primal nodes for numbering purposes */
41774f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
41784f1b2e48SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
41794f1b2e48SStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4180019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4181019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
4182019a44ceSStefano Zampini     pcbddc->local_primal_size++;
4183019a44ceSStefano Zampini   }
4184019a44ceSStefano Zampini 
4185019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
4186727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
4187727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
41889f47a83aSStefano 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);
4189c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
41900e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
41919f47a83aSStefano 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);
4192727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4193727cdba6SStefano Zampini     }
41940e6343abSStefano Zampini   }
41950e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4196727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4197727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4198727cdba6SStefano Zampini 
4199a717540cSStefano Zampini   /* flush dbg viewer */
4200b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4201b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4202b8ffe317SStefano Zampini   }
4203a717540cSStefano Zampini 
4204e310c8b4SStefano Zampini   /* free workspace */
4205a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
42064641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
420708122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
42089162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
42099162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
421008122e43SStefano Zampini   } else {
42119162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
42129162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
42139162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
421408122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
421508122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
42169162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
42179162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
421808122e43SStefano Zampini   }
4219674ae819SStefano Zampini   PetscFunctionReturn(0);
4220674ae819SStefano Zampini }
4221674ae819SStefano Zampini 
4222674ae819SStefano Zampini #undef __FUNCT__
4223674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4224674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4225674ae819SStefano Zampini {
4226674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4227674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4228674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
42297fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
4230674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
4231674ae819SStefano Zampini 
4232674ae819SStefano Zampini   PetscFunctionBegin;
42338e61c736SStefano Zampini   /* Reset previously computed graph */
42348e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4235674ae819SStefano Zampini   /* Init local Graph struct */
42367fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
42373bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4238674ae819SStefano Zampini 
4239575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
42405099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
42415099eff2SStefano 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);
4242575ad6abSStefano Zampini   }
42439577ea80SStefano Zampini 
4244674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4245d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
42464d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
42474d379d7bSStefano Zampini     PetscInt  nvtxs;
4248e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4249674ae819SStefano Zampini 
42502fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
42512fffb893SStefano Zampini     if (flg_row) {
42524d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4253b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
42542fffb893SStefano Zampini     }
42552fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4256674ae819SStefano Zampini   }
42579b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
42589b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4259674ae819SStefano Zampini   }
4260674ae819SStefano Zampini 
426163602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
4262674ae819SStefano Zampini   vertex_size = 1;
426363602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
426463602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
426595ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
426663602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
4267e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
426863602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
4269674ae819SStefano Zampini       }
427063602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
427163602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
427263602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
4273674ae819SStefano Zampini     }
427463602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
4275674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
427663602bcaSStefano Zampini   } else {
427763602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
427863602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
4279854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
428063602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
428163602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
428263602bcaSStefano Zampini       }
428363602bcaSStefano Zampini     }
4284674ae819SStefano Zampini   }
4285674ae819SStefano Zampini 
4286674ae819SStefano Zampini   /* Setup of Graph */
4287785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
4288e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
4289785d1243SStefano Zampini   }
4290785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
4291e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
4292785d1243SStefano Zampini   }
429330368db7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) { /* need to convert from global to local */
429430368db7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
429530368db7SStefano Zampini   }
429630368db7SStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
4297674ae819SStefano Zampini 
42984f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
42994f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
43004f1b2e48SStefano Zampini     PetscInt *local_subs;
43014f1b2e48SStefano Zampini 
43024f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
43034f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
43044f1b2e48SStefano Zampini       const PetscInt *idxs;
43054f1b2e48SStefano Zampini       PetscInt       nl,j;
43064f1b2e48SStefano Zampini 
43074f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
43084f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
43094f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
43104f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
43114f1b2e48SStefano Zampini       }
43124f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
43134f1b2e48SStefano Zampini     }
43144f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
43154f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
43164f1b2e48SStefano Zampini   }
43174f1b2e48SStefano Zampini 
4318674ae819SStefano Zampini   /* Graph's connected components analysis */
4319674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4320674ae819SStefano Zampini 
4321674ae819SStefano Zampini   /* print some info to stdout */
4322674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
4323302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
4324674ae819SStefano Zampini   }
4325fb180af4SStefano Zampini 
4326fb180af4SStefano Zampini   /* mark topography has done */
4327fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
4328674ae819SStefano Zampini   PetscFunctionReturn(0);
4329674ae819SStefano Zampini }
4330674ae819SStefano Zampini 
4331dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4332674ae819SStefano Zampini #undef __FUNCT__
4333674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4334dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4335674ae819SStefano Zampini {
4336dc456d91SStefano Zampini   PetscSF        sf;
4337dc456d91SStefano Zampini   PetscLayout    map;
4338dc456d91SStefano Zampini   const PetscInt *idxs;
4339dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4340dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4341dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4342dc456d91SStefano Zampini   PetscMPIInt    commsize;
4343674ae819SStefano Zampini   PetscBool      first_found;
4344674ae819SStefano Zampini   PetscErrorCode ierr;
4345674ae819SStefano Zampini 
4346674ae819SStefano Zampini   PetscFunctionBegin;
4347dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4348dc456d91SStefano Zampini   if (subset_mult) {
4349dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4350dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4351dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4352674ae819SStefano Zampini   }
4353dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4354dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4355dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4356dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4357dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4358dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4359674ae819SStefano Zampini   }
4360dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4361dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4362dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4363dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4364dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4365dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4366dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4367dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4368dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4369dc456d91SStefano Zampini 
4370dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4371dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4372dc456d91SStefano Zampini   if (subset_mult) {
4373dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4374dc456d91SStefano Zampini 
4375dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4376dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4377dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4378674ae819SStefano Zampini   } else {
4379dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4380674ae819SStefano Zampini   }
4381dc456d91SStefano Zampini   /* local size of new subset */
4382dc456d91SStefano Zampini   n_n = 0;
4383dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4384dc456d91SStefano Zampini 
4385dc456d91SStefano Zampini   /* global indexes in layout */
4386dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4387dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4388dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4389dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4390dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4391dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4392dc456d91SStefano Zampini 
4393dc456d91SStefano Zampini   /* reduce from leaves to roots */
4394dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
439564a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
439664a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4397dc456d91SStefano Zampini 
4398dc456d91SStefano Zampini   /* count indexes in local part of layout */
4399674ae819SStefano Zampini   nlocals = 0;
4400674ae819SStefano Zampini   first_index = -1;
4401674ae819SStefano Zampini   first_found = PETSC_FALSE;
4402dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4403dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4404674ae819SStefano Zampini       first_found = PETSC_TRUE;
4405674ae819SStefano Zampini       first_index = i;
4406674ae819SStefano Zampini     }
4407dc456d91SStefano Zampini     nlocals += root_data[i];
4408674ae819SStefano Zampini   }
4409dc456d91SStefano Zampini 
4410dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
44115fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4412dc456d91SStefano Zampini   start = 0;
441364a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
44145fa240b1SStefano Zampini #else
441564a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
44165fa240b1SStefano Zampini   start = start-nlocals;
44175fa240b1SStefano Zampini #endif
44185fa240b1SStefano Zampini 
4419dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4420dc456d91SStefano Zampini     *N_n = start + nlocals;
4421dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4422dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4423674ae819SStefano Zampini   }
44245fa240b1SStefano Zampini 
44255fa240b1SStefano Zampini   /* adapt root data with cumulative */
4426674ae819SStefano Zampini   if (first_found) {
4427dc456d91SStefano Zampini     PetscInt old_index;
4428dc456d91SStefano Zampini 
4429dc456d91SStefano Zampini     root_data[first_index] += start;
4430674ae819SStefano Zampini     old_index = first_index;
4431dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4432dc456d91SStefano Zampini       if (root_data[i]) {
4433dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4434674ae819SStefano Zampini         old_index = i;
4435674ae819SStefano Zampini       }
4436674ae819SStefano Zampini     }
4437674ae819SStefano Zampini   }
4438dc456d91SStefano Zampini 
4439dc456d91SStefano Zampini   /* from roots to leaves */
4440dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4441dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4442dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4443dc456d91SStefano Zampini 
4444dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4445dc456d91SStefano Zampini   if (subset_mult) {
4446dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4447dc456d91SStefano Zampini     PetscInt        cum;
4448dc456d91SStefano Zampini 
4449dc456d91SStefano Zampini     cum = 0;
4450dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4451dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4452dc456d91SStefano Zampini       PetscInt j;
4453dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4454674ae819SStefano Zampini     }
4455dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4456674ae819SStefano Zampini   } else {
4457dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4458dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4459674ae819SStefano Zampini     }
4460674ae819SStefano Zampini   }
4461dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4462dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4463674ae819SStefano Zampini   PetscFunctionReturn(0);
4464674ae819SStefano Zampini }
44659a7d3425SStefano Zampini 
44669a7d3425SStefano Zampini #undef __FUNCT__
44679a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
44689a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
44699a7d3425SStefano Zampini {
44709a7d3425SStefano Zampini   PetscInt       i,j;
44719a7d3425SStefano Zampini   PetscScalar    *alphas;
44729a7d3425SStefano Zampini   PetscErrorCode ierr;
44739a7d3425SStefano Zampini 
44749a7d3425SStefano Zampini   PetscFunctionBegin;
44759a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4476785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
44779a7d3425SStefano Zampini   for (i=0;i<n;i++) {
44789a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
44799a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
44809a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
44819a7d3425SStefano Zampini   }
44829a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
44839a7d3425SStefano Zampini   PetscFunctionReturn(0);
44849a7d3425SStefano Zampini }
44859a7d3425SStefano Zampini 
4486e7931f94SStefano Zampini #undef __FUNCT__
448770cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
4488b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
4489e7931f94SStefano Zampini {
449052e5ac9dSStefano Zampini   IS             ranks_send_to;
4491e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4492e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
449352e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
449452e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
44953837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
44962b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
4497e7931f94SStefano Zampini   PetscSubcomm   subcomm;
449852e5ac9dSStefano Zampini   PetscErrorCode ierr;
4499a57a6d2fSStefano Zampini 
4500e7931f94SStefano Zampini   PetscFunctionBegin;
45012b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
45022b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
45032b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
4504e7931f94SStefano Zampini 
4505e7931f94SStefano Zampini   /* Get info on mapping */
45063bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
45073bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4508e7931f94SStefano Zampini 
4509e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4510785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4511e7931f94SStefano Zampini   xadj[0] = 0;
4512e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4513785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4514785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
4515e7931f94SStefano Zampini 
45162b510759SStefano Zampini   if (threshold) {
4517d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
45182b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
4519d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
4520d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4521d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4522d023bfaeSStefano Zampini         xadj_count++;
4523e7931f94SStefano Zampini       }
4524e7931f94SStefano Zampini     }
4525d023bfaeSStefano Zampini     xadj[1] = xadj_count;
4526c8587f34SStefano Zampini   } else {
4527e7931f94SStefano Zampini     if (xadj[1]) {
4528e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
4529e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
4530c8587f34SStefano Zampini     }
4531e7931f94SStefano Zampini   }
45323bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4533e7931f94SStefano Zampini   if (use_square) {
4534e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4535e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
4536e7931f94SStefano Zampini     }
4537e7931f94SStefano Zampini   }
4538e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4539e7931f94SStefano Zampini 
45403837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4541e7931f94SStefano Zampini 
4542e7931f94SStefano Zampini   /*
4543e7931f94SStefano Zampini     Restrict work on active processes only.
4544e7931f94SStefano Zampini   */
4545e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
4546e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
4547e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
45482b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
4549d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4550e7931f94SStefano Zampini   if (color) {
4551e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4552e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4553e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4554c8587f34SStefano Zampini   } else {
455552e5ac9dSStefano Zampini     Mat             subdomain_adj;
455652e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
455752e5ac9dSStefano Zampini     MatPartitioning partitioner;
455852e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
455952e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
4560b0c7d250SStefano Zampini     PetscBool       aggregate;
4561b0c7d250SStefano Zampini 
4562306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
4563785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
4564e7931f94SStefano Zampini     prank = rank;
4565306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
45668002ef2cSStefano Zampini     /*
4567e7931f94SStefano Zampini     for (i=0;i<size;i++) {
4568e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
4569c8587f34SStefano Zampini     }
45708002ef2cSStefano Zampini     */
4571e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4572e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4573c8587f34SStefano Zampini     }
4574e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4575b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
4576b0c7d250SStefano Zampini     if (aggregate) {
4577b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
4578b0c7d250SStefano Zampini       PetscMPIInt nrank;
4579b0c7d250SStefano Zampini       PetscScalar *vals;
4580b0c7d250SStefano Zampini 
4581b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
4582b0c7d250SStefano Zampini       lrows = 0;
4583b0c7d250SStefano Zampini       if (nrank<redprocs) {
4584b0c7d250SStefano Zampini         lrows = size/redprocs;
4585b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
4586b0c7d250SStefano Zampini       }
45875fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
4588b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
4589b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4590b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4591b0c7d250SStefano Zampini       row = nrank;
4592b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
4593b0c7d250SStefano Zampini       cols = adjncy;
4594b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
4595b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
4596b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
4597b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4598b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
459952e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
460052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
460152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4602b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
4603b0c7d250SStefano Zampini     } else {
4604306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
4605b0c7d250SStefano Zampini     }
460622b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
4607e7931f94SStefano Zampini 
4608e7931f94SStefano Zampini     /* Partition */
4609306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
4610e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
4611e7931f94SStefano Zampini     if (use_vwgt) {
46123837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
4613e7931f94SStefano Zampini       v_wgt[0] = local_size;
4614e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
4615c8587f34SStefano Zampini     }
461628143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
461728143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
4618e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
4619e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
462022b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
4621e7931f94SStefano Zampini 
462252e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
462352e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
462452e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
462552e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4626b0c7d250SStefano Zampini     if (!redprocs) {
4627b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
462828143c3dSStefano Zampini     } else {
4629b0c7d250SStefano Zampini       PetscInt    idxs[1];
4630b0c7d250SStefano Zampini       PetscMPIInt tag;
4631b0c7d250SStefano Zampini       MPI_Request *reqs;
4632b0c7d250SStefano Zampini 
4633b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
4634b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
4635b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
4636b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
463728143c3dSStefano Zampini       }
4638b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
4639b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4640b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
4641b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
4642e7931f94SStefano Zampini     }
464352e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4644e7931f94SStefano Zampini     /* clean up */
4645e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
464652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
4647e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
4648e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
4649e7931f94SStefano Zampini   }
4650e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
4651e7931f94SStefano Zampini 
4652e7931f94SStefano Zampini   /* assemble parallel IS for sends */
4653e7931f94SStefano Zampini   i = 1;
4654e7931f94SStefano Zampini   if (color) i=0;
4655e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
4656e7931f94SStefano Zampini   /* get back IS */
4657e7931f94SStefano Zampini   *is_sends = ranks_send_to;
4658e7931f94SStefano Zampini   PetscFunctionReturn(0);
4659e7931f94SStefano Zampini }
4660e7931f94SStefano Zampini 
4661e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
4662e7931f94SStefano Zampini 
4663e7931f94SStefano Zampini #undef __FUNCT__
4664e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
466553a05cb3SStefano 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[])
4666e7931f94SStefano Zampini {
466770cf5478SStefano Zampini   Mat                    local_mat;
4668e7931f94SStefano Zampini   IS                     is_sends_internal;
46699d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
467028143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
46719d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
4672e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
4673e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
4674e7931f94SStefano Zampini   const PetscInt*        is_indices;
4675e7931f94SStefano Zampini   MatType                new_local_type;
4676e7931f94SStefano Zampini   /* buffers */
4677e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
467828143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
46799d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
4680e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
4681e7931f94SStefano Zampini   /* MPI */
468228143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
468328143c3dSStefano Zampini   PetscSubcomm           subcomm;
4684e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
468528143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
468628143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
468728143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
468828143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
468928143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
4690e7931f94SStefano Zampini   PetscErrorCode         ierr;
4691e7931f94SStefano Zampini 
4692e7931f94SStefano Zampini   PetscFunctionBegin;
469328143c3dSStefano Zampini   /* TODO: add missing checks */
469428143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
469528143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
469628143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
469728143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
4698e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
469928143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
4700e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4701e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
4702e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
4703e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
4704e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
470528143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
470670cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
470770cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
470828143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
470970cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
471070cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
471170cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
471270cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
471370cf5478SStefano Zampini   }
4714e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
4715e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
4716e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
4717e7931f94SStefano Zampini   if (!is_sends) {
471828143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
4719b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
4720c8587f34SStefano Zampini   } else {
4721e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
4722e7931f94SStefano Zampini     is_sends_internal = is_sends;
4723c8587f34SStefano Zampini   }
4724e7931f94SStefano Zampini 
4725e7931f94SStefano Zampini   /* get comm */
4726a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4727e7931f94SStefano Zampini 
4728e7931f94SStefano Zampini   /* compute number of sends */
4729e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4730e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4731e7931f94SStefano Zampini 
4732e7931f94SStefano Zampini   /* compute number of receives */
4733e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4734785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4735e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4736e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4737e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4738e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4739e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
4740e7931f94SStefano Zampini 
474128143c3dSStefano Zampini   /* restrict comm if requested */
474228143c3dSStefano Zampini   subcomm = 0;
474328143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
474428143c3dSStefano Zampini   if (restrict_comm) {
4745779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
4746779c1cceSStefano Zampini 
474728143c3dSStefano Zampini     color = 0;
474853a05cb3SStefano Zampini     if (restrict_full) {
474953a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
475053a05cb3SStefano Zampini     } else {
475153a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
475253a05cb3SStefano Zampini     }
475328143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
475428143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
475528143c3dSStefano Zampini     /* check if reuse has been requested */
475628143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
475728143c3dSStefano Zampini       if (*mat_n) {
475828143c3dSStefano Zampini         PetscMPIInt subcommsize2;
475928143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
476028143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
476128143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
476228143c3dSStefano Zampini       } else {
476328143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
476428143c3dSStefano Zampini       }
476528143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
4766779c1cceSStefano Zampini       PetscMPIInt rank;
4767779c1cceSStefano Zampini 
4768779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
476928143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
477028143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
477128143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4772306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
477328143c3dSStefano Zampini     }
477428143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
477528143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
477628143c3dSStefano Zampini   } else {
477728143c3dSStefano Zampini     comm_n = comm;
477828143c3dSStefano Zampini   }
477928143c3dSStefano Zampini 
4780e7931f94SStefano Zampini   /* prepare send/receive buffers */
4781785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4782e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4783785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4784e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
478528143c3dSStefano Zampini   if (nis) {
4786854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
478728143c3dSStefano Zampini   }
4788e7931f94SStefano Zampini 
478928143c3dSStefano Zampini   /* Get data from local matrices */
4790e7931f94SStefano Zampini   if (!isdense) {
4791a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4792e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4793e7931f94SStefano Zampini     /*
4794e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4795e7931f94SStefano Zampini        send_buffer_idxs should contain:
4796e7931f94SStefano Zampini        - MatType_PRIVATE type
4797e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4798e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4799e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4800e7931f94SStefano Zampini     */
4801e7931f94SStefano Zampini   } else {
4802e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
48033bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4804854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4805e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4806e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
48073bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4808e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
48093bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4810e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4811e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4812e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4813e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4814c8587f34SStefano Zampini     }
4815c8587f34SStefano Zampini   }
4816e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
481728143c3dSStefano Zampini   /* additional is (if any) */
481828143c3dSStefano Zampini   if (nis) {
481928143c3dSStefano Zampini     PetscMPIInt psum;
482028143c3dSStefano Zampini     PetscInt j;
482128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
482228143c3dSStefano Zampini       PetscInt plen;
482328143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
482428143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
482528143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
482628143c3dSStefano Zampini     }
4827854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
482828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
482928143c3dSStefano Zampini       PetscInt plen;
483028143c3dSStefano Zampini       const PetscInt *is_array_idxs;
483128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
483228143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
483328143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
483428143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
483528143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
483628143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
483728143c3dSStefano Zampini     }
483828143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
483928143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
484028143c3dSStefano Zampini     }
484128143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
484228143c3dSStefano Zampini   }
484328143c3dSStefano Zampini 
4844e7931f94SStefano Zampini   buf_size_idxs = 0;
4845e7931f94SStefano Zampini   buf_size_vals = 0;
484628143c3dSStefano Zampini   buf_size_idxs_is = 0;
4847e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4848e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4849e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
485028143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4851e7931f94SStefano Zampini   }
4852785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4853785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
485495ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4855e7931f94SStefano Zampini 
4856e7931f94SStefano Zampini   /* get new tags for clean communications */
4857e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4858e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
485928143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4860e7931f94SStefano Zampini 
4861e7931f94SStefano Zampini   /* allocate for requests */
4862785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4863785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
486495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4865785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4866785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
486795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4868e7931f94SStefano Zampini 
4869e7931f94SStefano Zampini   /* communications */
4870e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4871e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
487228143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4873e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4874e7931f94SStefano Zampini     source_dest = onodes[i];
4875e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4876e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4877e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4878e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
487928143c3dSStefano Zampini     if (nis) {
488028143c3dSStefano 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);
488128143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
488228143c3dSStefano Zampini     }
4883e7931f94SStefano Zampini   }
4884e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4885e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4886e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4887e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
488828143c3dSStefano Zampini     if (nis) {
488928143c3dSStefano 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);
489028143c3dSStefano Zampini     }
4891e7931f94SStefano Zampini   }
4892e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4893e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4894e7931f94SStefano Zampini 
4895e7931f94SStefano Zampini   /* assemble new l2g map */
4896e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4897e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
48989d30be91SStefano Zampini   new_local_rows = 0;
4899e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
49009d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4901e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4902e7931f94SStefano Zampini   }
49039d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4904e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
49059d30be91SStefano Zampini   new_local_rows = 0;
4906e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
49079d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
49089d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4909e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4910e7931f94SStefano Zampini   }
49119d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
49129d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4913e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4914e7931f94SStefano Zampini 
4915e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4916e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4917e7931f94SStefano 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) */
4918e7931f94SStefano Zampini   if (n_recvs) {
491928143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4920e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4921e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4922e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4923e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4924e7931f94SStefano Zampini         break;
4925e7931f94SStefano Zampini       }
4926e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4927e7931f94SStefano Zampini     }
4928e7931f94SStefano Zampini     switch (new_local_type_private) {
492928143c3dSStefano Zampini       case MATDENSE_PRIVATE:
493028143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4931e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4932e7931f94SStefano Zampini           bs = 1;
493328143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
493428143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
493528143c3dSStefano Zampini           bs = 1;
493628143c3dSStefano Zampini         }
4937e7931f94SStefano Zampini         break;
4938e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4939e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4940e7931f94SStefano Zampini         bs = 1;
4941e7931f94SStefano Zampini         break;
4942e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4943e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4944e7931f94SStefano Zampini         break;
4945e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4946e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4947e7931f94SStefano Zampini         break;
4948e7931f94SStefano Zampini       default:
49499d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4950e7931f94SStefano Zampini         break;
4951e7931f94SStefano Zampini     }
495228143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
495328143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
495428143c3dSStefano Zampini     bs = 1;
4955e7931f94SStefano Zampini   }
4956e7931f94SStefano Zampini 
495770cf5478SStefano Zampini   /* create MATIS object if needed */
495870cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4959e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4960e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
496170cf5478SStefano Zampini   } else {
496270cf5478SStefano Zampini     /* it also destroys the local matrices */
496370cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
496470cf5478SStefano Zampini   }
496570cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4966e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
49679d30be91SStefano Zampini 
49689d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
49699d30be91SStefano Zampini 
49709d30be91SStefano Zampini   /* Global to local map of received indices */
49719d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
49729d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
49739d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
49749d30be91SStefano Zampini 
49759d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
49769d30be91SStefano Zampini   buf_size_idxs = 0;
49779d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
49789d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
49799d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
49809d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
49819d30be91SStefano Zampini   }
49829d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
49839d30be91SStefano Zampini 
49849d30be91SStefano Zampini   /* set preallocation */
49859d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
49869d30be91SStefano Zampini   if (!newisdense) {
49879d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
49889d30be91SStefano Zampini 
49899d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
49909d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
49919d30be91SStefano Zampini     if (n_recvs) {
49929d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
49939d30be91SStefano Zampini     }
49949d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
49959d30be91SStefano Zampini       PetscInt j;
49969d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
49979d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
49989d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
49999d30be91SStefano Zampini         }
50009d30be91SStefano Zampini       } else {
50019d30be91SStefano Zampini         /* TODO */
50029d30be91SStefano Zampini       }
50039d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
50049d30be91SStefano Zampini     }
50059d30be91SStefano Zampini     if (new_local_nnz) {
50069d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
50079d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
50089d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
50099d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
50109d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
50119d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
50129d30be91SStefano Zampini     } else {
50139d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
50149d30be91SStefano Zampini     }
50159d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
50169d30be91SStefano Zampini   } else {
50179d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
50189d30be91SStefano Zampini   }
5019e7931f94SStefano Zampini 
5020e7931f94SStefano Zampini   /* set values */
5021e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
50229d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5023e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5024e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5025e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
50269d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5027e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5028e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5029e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
503028143c3dSStefano Zampini     } else {
503128143c3dSStefano Zampini       /* TODO */
5032e7931f94SStefano Zampini     }
5033e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5034e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5035e7931f94SStefano Zampini   }
5036e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5037e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
503870cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
503970cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
50409d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
50419d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5042e7931f94SStefano Zampini 
5043dfd14d43SStefano Zampini #if 0
504428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5045e7931f94SStefano Zampini     Vec       lvec,rvec;
5046e7931f94SStefano Zampini     PetscReal infty_error;
5047e7931f94SStefano Zampini 
50482a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5049e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5050e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5051e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
505270cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5053e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5054e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5055e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5056e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5057e7931f94SStefano Zampini   }
505828143c3dSStefano Zampini #endif
5059e7931f94SStefano Zampini 
506028143c3dSStefano Zampini   /* assemble new additional is (if any) */
506128143c3dSStefano Zampini   if (nis) {
506228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
506328143c3dSStefano Zampini 
506428143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5065854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
506628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
506728143c3dSStefano Zampini     psum = 0;
506828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
506928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
507028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
507128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
507228143c3dSStefano Zampini         psum += plen;
507328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
507428143c3dSStefano Zampini       }
507528143c3dSStefano Zampini     }
5076854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5077854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
507828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
507928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
508028143c3dSStefano Zampini     }
508128143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
508228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
508328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
508428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
508528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
508628143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
508728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
508828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
508928143c3dSStefano Zampini       }
509028143c3dSStefano Zampini     }
509128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
509228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
509328143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
509428143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
509528143c3dSStefano Zampini     }
509628143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
509728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
509828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
509928143c3dSStefano Zampini   }
5100e7931f94SStefano Zampini   /* free workspace */
510128143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5102e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5103e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5104e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5105e7931f94SStefano Zampini   if (isdense) {
5106e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5107e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5108e7931f94SStefano Zampini   } else {
5109e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5110e7931f94SStefano Zampini   }
511128143c3dSStefano Zampini   if (nis) {
511228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
511328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
511428143c3dSStefano Zampini   }
5115e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5116e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
511728143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5118e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5119e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
512028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5121e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5122e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5123e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5124e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5125e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
512628143c3dSStefano Zampini   if (nis) {
512728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
512828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
512928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
513028143c3dSStefano Zampini   }
513128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
513228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
513328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
513428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
513528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
513628143c3dSStefano Zampini     }
513753a05cb3SStefano Zampini     *mat_n = NULL;
513828143c3dSStefano Zampini   }
5139e7931f94SStefano Zampini   PetscFunctionReturn(0);
5140e7931f94SStefano Zampini }
5141a57a6d2fSStefano Zampini 
514212edc857SStefano Zampini /* temporary hack into ksp private data structure */
5143af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
514412edc857SStefano Zampini 
5145c8587f34SStefano Zampini #undef __FUNCT__
5146c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5147c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5148c8587f34SStefano Zampini {
5149c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5150c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
515120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
51529881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
515320a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
51546e683305SStefano Zampini   IS                     coarse_is,*isarray;
51556e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
515630368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5157f9eb5b7dSStefano Zampini   PC                     pc_temp;
5158c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5159c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5160f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
51614f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
51626e683305SStefano Zampini   Mat                    t_coarse_mat_is;
51636e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
51646e683305SStefano Zampini   PetscMPIInt            all_procs;
516574e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
516668457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
516722bc73bbSStefano Zampini   PetscScalar            *array;
51689881197aSStefano Zampini   PetscErrorCode         ierr;
5169fdc09c96SStefano Zampini 
5170c8587f34SStefano Zampini   PetscFunctionBegin;
5171c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
517268457ee5SStefano 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 */
5173fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
51745a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5175fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5176f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5177f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5178f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5179fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
518051bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
518151bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5182dc4bcba2SStefano Zampini         PC        pc;
5183dc4bcba2SStefano Zampini         PetscBool isbddc;
5184dc4bcba2SStefano Zampini 
5185dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5186dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5187dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5188dc4bcba2SStefano Zampini         if (isbddc) {
5189*63c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
5190*63c961adSStefano Zampini         } else {
5191727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
5192*63c961adSStefano Zampini         }
5193fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5194fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5195fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5196f4ddd8eeSStefano Zampini       }
5197fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5198fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5199f4ddd8eeSStefano Zampini     }
520070cf5478SStefano Zampini     /* reset any subassembling information */
520170cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
52026e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
52036e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5204fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5205f4ddd8eeSStefano Zampini   }
5206c8587f34SStefano Zampini 
52076e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
52082b510759SStefano Zampini   im_active = !!(pcis->n);
52092b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
52106e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
52116e683305SStefano Zampini   void_procs = all_procs-active_procs;
52126e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
521374e2c79eSStefano Zampini   redist = PETSC_FALSE;
521422bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
52156e683305SStefano Zampini     csin_ml = PETSC_TRUE;
52166e683305SStefano Zampini     ncoarse_ml = void_procs;
5217779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
5218779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
52196e683305SStefano Zampini       csin_ds = PETSC_TRUE;
522018a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
522118a45a71SStefano Zampini       redist = PETSC_TRUE;
522218a45a71SStefano Zampini     } else {
52236e683305SStefano Zampini       csin_ds = PETSC_TRUE;
5224779c1cceSStefano Zampini       ncoarse_ds = active_procs;
5225779c1cceSStefano Zampini       redist = PETSC_TRUE;
522618a45a71SStefano Zampini     }
52276e683305SStefano Zampini   } else {
52286e683305SStefano Zampini     csin_ml = PETSC_FALSE;
52296e683305SStefano Zampini     ncoarse_ml = all_procs;
52306e683305SStefano Zampini     if (void_procs) {
52316e683305SStefano Zampini       csin_ds = PETSC_TRUE;
52326e683305SStefano Zampini       ncoarse_ds = void_procs;
52336e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
52346e683305SStefano Zampini     } else {
5235779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
523674e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
523774e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
523874e2c79eSStefano Zampini         redist = PETSC_TRUE;
523974e2c79eSStefano Zampini       } else {
52406e683305SStefano Zampini         csin_ds = PETSC_FALSE;
52416e683305SStefano Zampini         ncoarse_ds = all_procs;
52426e683305SStefano Zampini       }
52436e683305SStefano Zampini     }
524474e2c79eSStefano Zampini   }
52456e683305SStefano Zampini 
52466e683305SStefano Zampini   /*
52476e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
52486e683305SStefano Zampini     - we have not exceeded the number of levels requested
52496e683305SStefano Zampini     - we can actually subassemble the active processes
52506e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
52516e683305SStefano Zampini   */
52526e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
52536e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
52546e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
52556e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
52566e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
5257f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
52582b510759SStefano Zampini     } else {
5259f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
5260c8587f34SStefano Zampini     }
5261c8587f34SStefano Zampini   }
52626e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
52636e683305SStefano Zampini   if (multilevel_allowed) {
52646e683305SStefano Zampini     ncoarse = ncoarse_ml;
52656e683305SStefano Zampini     csin = csin_ml;
526658da7f69SStefano Zampini     redist = PETSC_FALSE;
52676e683305SStefano Zampini   } else {
52686e683305SStefano Zampini     ncoarse = ncoarse_ds;
52696e683305SStefano Zampini     csin = csin_ds;
52706e683305SStefano Zampini   }
5271e7931f94SStefano Zampini 
5272abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5273abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5274abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5275abbbba34SStefano Zampini 
5276abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
527722bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
527822bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
527922bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
528022bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5281e176bc59SStefano 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);
52826e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
52836e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
52846e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5285abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5286abbbba34SStefano Zampini 
52876e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
528830368db7SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local))) { /* protects from unneded computations */
52896e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
52906e683305SStefano Zampini     const PetscInt         *idxs;
52916e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
52926e683305SStefano Zampini 
52936e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
52940be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
52956e683305SStefano Zampini     /* allocate space for temporary storage */
5296854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5297854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
52986e683305SStefano Zampini     /* allocate for IS array */
52996e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
53006e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
530130368db7SStefano Zampini     nisvert = 0;
530230368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
530330368db7SStefano Zampini       nisvert = 1;
530430368db7SStefano Zampini     }
530530368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5306854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
53076e683305SStefano Zampini     /* dofs splitting */
53086e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
53096e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
53106e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
53116e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
53126e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
53136e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
53146e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
531530368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
53166e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
53176e683305SStefano Zampini     }
53186e683305SStefano Zampini     /* neumann boundaries */
53196e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
53206e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
53216e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
53226e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
53236e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
53246e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
53256e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
532630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
53276e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
53286e683305SStefano Zampini     }
532930368db7SStefano Zampini     /* primal vertices (benign) */
533030368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
533130368db7SStefano Zampini       ierr = ISGetLocalSize(pcbddc->user_primal_vertices_local,&tsize);CHKERRQ(ierr);
533230368db7SStefano Zampini       ierr = ISGetIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
533330368db7SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
533430368db7SStefano Zampini       ierr = ISRestoreIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
533530368db7SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
533630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nis-1]);CHKERRQ(ierr);
533730368db7SStefano Zampini     }
53386e683305SStefano Zampini     /* free memory */
53396e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
53406e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
53416e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
53426e683305SStefano Zampini   } else {
53436e683305SStefano Zampini     nis = 0;
53446e683305SStefano Zampini     nisdofs = 0;
53456e683305SStefano Zampini     nisneu = 0;
534630368db7SStefano Zampini     nisvert = 0;
53476e683305SStefano Zampini     isarray = NULL;
53486e683305SStefano Zampini   }
53496e683305SStefano Zampini   /* destroy no longer needed map */
53506e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
53516e683305SStefano Zampini 
53526e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
53536e683305SStefano Zampini   coarse_mat_is = NULL;
53546e683305SStefano Zampini   if (csin) {
53556e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
535674e2c79eSStefano Zampini       if (redist) {
535774e2c79eSStefano Zampini         PetscMPIInt rank;
5358779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
535974e2c79eSStefano Zampini 
536074e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
536158da7f69SStefano Zampini         spc = active_procs/ncoarse;
536258da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
5363779c1cceSStefano Zampini         if (im_active) {
5364779c1cceSStefano Zampini           destsize = 1;
536574e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
536674e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
536774e2c79eSStefano Zampini           } else {
536874e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
536974e2c79eSStefano Zampini           }
537074e2c79eSStefano Zampini         } else {
5371779c1cceSStefano Zampini           destsize = 0;
53726e683305SStefano Zampini         }
5373779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5374779c1cceSStefano Zampini       } else if (csin_type_simple) {
53756e683305SStefano Zampini         PetscMPIInt rank;
53766e683305SStefano Zampini         PetscInt    issize,isidx;
5377779c1cceSStefano Zampini 
53786e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
53796e683305SStefano Zampini         if (im_active) {
53806e683305SStefano Zampini           issize = 1;
53816e683305SStefano Zampini           isidx = (PetscInt)rank;
53826e683305SStefano Zampini         } else {
53836e683305SStefano Zampini           issize = 0;
53846e683305SStefano Zampini           isidx = -1;
53856e683305SStefano Zampini         }
53866e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5387779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
5388b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
53896e683305SStefano Zampini       }
5390779c1cceSStefano Zampini 
5391779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
5392779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
5393779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
5394779c1cceSStefano Zampini         PetscInt *coarse_candidates;
5395779c1cceSStefano Zampini         const PetscInt* tisindices;
5396779c1cceSStefano Zampini 
5397779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
5398779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
5399779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5400779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
5401779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
5402779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
5403779c1cceSStefano Zampini           }
5404779c1cceSStefano Zampini         }
5405779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
5406779c1cceSStefano Zampini 
5407779c1cceSStefano Zampini 
54086e683305SStefano Zampini         if (pcbddc->dbg_flag) {
54096e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54106e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
54116e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
54126e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
5413779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
54146e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
54156e683305SStefano Zampini           }
54166e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
54176e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54186e683305SStefano Zampini         }
54196e683305SStefano Zampini         /* shift the pattern on coarse candidates */
54206e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
54216e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
5422854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
54236e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
54246e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
54256e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
54266e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
54276e683305SStefano Zampini       }
54286e683305SStefano Zampini       if (pcbddc->dbg_flag) {
54296e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54306e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
54316e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
54326e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54336e683305SStefano Zampini       }
5434779c1cceSStefano Zampini     }
54356e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
543653a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
543753a05cb3SStefano 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);
543853a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
543953a05cb3SStefano 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);
544053a05cb3SStefano Zampini     }
54416e683305SStefano Zampini   } else {
54426e683305SStefano Zampini     if (pcbddc->dbg_flag) {
54436e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54446e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
54456e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54466e683305SStefano Zampini     }
54476e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
54486e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
54496e683305SStefano Zampini   }
54506e683305SStefano Zampini 
54516e683305SStefano Zampini   /* create local to global scatters for coarse problem */
545268457ee5SStefano Zampini   if (compute_vecs) {
54536e683305SStefano Zampini     PetscInt lrows;
54546e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
54556e683305SStefano Zampini     if (coarse_mat_is) {
54566e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
54576e683305SStefano Zampini     } else {
54586e683305SStefano Zampini       lrows = 0;
54596e683305SStefano Zampini     }
54606e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
54616e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
54626e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
54636e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
54646e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
54656e683305SStefano Zampini   }
54666e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
54676e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
5468c8587f34SStefano Zampini 
5469f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5470f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5471f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5472f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5473f9eb5b7dSStefano Zampini   } else {
5474f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5475f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5476c8587f34SStefano Zampini   }
5477c8587f34SStefano Zampini 
54786e683305SStefano Zampini   /* print some info if requested */
54796e683305SStefano Zampini   if (pcbddc->dbg_flag) {
54806e683305SStefano Zampini     if (!multilevel_allowed) {
54816e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
54826e683305SStefano Zampini       if (multilevel_requested) {
54836e683305SStefano 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);
54846e683305SStefano Zampini       } else if (pcbddc->max_levels) {
54856e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
54866e683305SStefano Zampini       }
54876e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
54886e683305SStefano Zampini     }
54896e683305SStefano Zampini   }
54906e683305SStefano Zampini 
5491f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
54926e683305SStefano Zampini   if (coarse_mat_is) {
54936e683305SStefano Zampini     MatReuse coarse_mat_reuse;
54946a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
54956e683305SStefano Zampini     if (pcbddc->dbg_flag) {
54966e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
54976e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
54986e683305SStefano Zampini     }
5499f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5500312be037SStefano Zampini       char prefix[256],str_level[16];
5501e604994aSStefano Zampini       size_t len;
55026e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5503422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5504c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5505f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
55065f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
5507c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
55086e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5509c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5510c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5511e604994aSStefano Zampini       /* prefix */
5512e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5513e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5514e604994aSStefano Zampini       if (!pcbddc->current_level) {
5515e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5516e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5517c8587f34SStefano Zampini       } else {
5518e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5519312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5520312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
552134d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5522312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5523e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5524e604994aSStefano Zampini       }
5525e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
55263e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
55273e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
55283e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
55293e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5530f9eb5b7dSStefano Zampini       /* allow user customization */
5531f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
55323e3c6dadSStefano Zampini     }
55333e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
553451bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
55353e3c6dadSStefano Zampini     if (nisdofs) {
55363e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
55373e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
55383e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
55393e3c6dadSStefano Zampini       }
55403e3c6dadSStefano Zampini     }
55413e3c6dadSStefano Zampini     if (nisneu) {
55423e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
55433e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5544312be037SStefano Zampini     }
554530368db7SStefano Zampini     if (nisvert) {
554630368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
554730368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
554830368db7SStefano Zampini     }
5549f9eb5b7dSStefano Zampini 
5550f9eb5b7dSStefano Zampini     /* get some info after set from options */
5551f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5552f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
55534f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
55546e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5555f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5556f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5557f9eb5b7dSStefano Zampini     }
555839f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
55594f3a063dSStefano Zampini     if (isredundant) {
55604f3a063dSStefano Zampini       KSP inner_ksp;
55614f3a063dSStefano Zampini       PC  inner_pc;
55624f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
55634f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
55644f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
55654f3a063dSStefano Zampini     }
5566f9eb5b7dSStefano Zampini 
5567f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
5568fa7f1dd8SStefano Zampini     if (coarse_reuse) {
556981d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
5570fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
55716e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
5572fa7f1dd8SStefano Zampini     } else {
55736e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
5574fa7f1dd8SStefano Zampini     }
5575c8587f34SStefano Zampini     if (isbddc || isnn) {
5576d4d8cf7bSStefano Zampini       if (isbddc) { /* currently there's no API for this */
5577d4d8cf7bSStefano Zampini         PC_BDDC* pcbddc = (PC_BDDC*)pc_temp->data;
5578d4d8cf7bSStefano Zampini         pcbddc->detect_disconnected = PETSC_TRUE;
5579d4d8cf7bSStefano Zampini       }
558022bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
558170cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
5582b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
558322b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
55846e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
55856e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
55866e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
55876e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
558822b6e8a2SStefano Zampini           }
558970cf5478SStefano Zampini         }
559053a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
559170cf5478SStefano Zampini       } else {
559222bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
559322bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
559422bc73bbSStefano Zampini       }
559522bc73bbSStefano Zampini     } else {
55962e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
5597c8587f34SStefano Zampini     }
5598c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
5599c8587f34SStefano Zampini 
56003301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
56015a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
56023301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
56033301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
56043301b35fSStefano Zampini     }
56053301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
56063301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
56073301b35fSStefano Zampini     }
56083301b35fSStefano Zampini     if (pc->pmat->spd_set) {
56093301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
56103301b35fSStefano Zampini     }
56116e683305SStefano Zampini     /* set operators */
56125f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
56136e683305SStefano Zampini     if (pcbddc->dbg_flag) {
56146e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
56156e683305SStefano Zampini     }
56166e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
56176e683305SStefano Zampini     coarse_mat = 0;
56186e683305SStefano Zampini   }
56196e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
5620b1ecc7b1SStefano Zampini #if 0
5621b9b85e73SStefano Zampini   {
5622b9b85e73SStefano Zampini     PetscViewer viewer;
5623b9b85e73SStefano Zampini     char filename[256];
5624b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
5625b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
5626b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5627b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
5628b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5629b9b85e73SStefano Zampini   }
5630b9b85e73SStefano Zampini #endif
5631c8587f34SStefano Zampini 
5632c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
5633298c0119SStefano Zampini #if 0
5634c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
5635c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
563698a51de6SStefano Zampini   }
5637298c0119SStefano Zampini #endif
5638b0f5fe93SStefano Zampini   /* hack */
563998a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
564098a51de6SStefano Zampini     Vec crhs,csol;
564104708bb6SStefano Zampini 
5642f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
5643f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
5644f347579bSStefano Zampini     if (!csol) {
56452a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
5646f9eb5b7dSStefano Zampini     }
5647f347579bSStefano Zampini     if (!crhs) {
56482a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
5649f347579bSStefano Zampini     }
5650b0f5fe93SStefano Zampini   }
5651b0f5fe93SStefano Zampini 
5652b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
5653b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
5654b0f5fe93SStefano Zampini 
5655b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
56564f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
56574f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
56584f1b2e48SStefano Zampini     }
5659b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
5660b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
5661b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5662b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5663b0f5fe93SStefano Zampini     if (coarse_mat) {
5664b0f5fe93SStefano Zampini       Vec         nullv;
5665b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
5666b0f5fe93SStefano Zampini       PetscInt    nl;
5667b0f5fe93SStefano Zampini 
5668b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
5669b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
5670b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5671b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
5672b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
5673b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
5674b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5675b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
5676b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
5677b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
5678b0f5fe93SStefano Zampini     }
5679b0f5fe93SStefano Zampini   }
5680b0f5fe93SStefano Zampini 
5681b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
5682b0f5fe93SStefano Zampini     PetscBool ispreonly;
5683b0f5fe93SStefano Zampini 
5684b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
5685b0f5fe93SStefano Zampini       PetscBool isnull;
5686b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
5687d4d8cf7bSStefano Zampini       if (0) {
568830368db7SStefano Zampini         if (isbddc && !pcbddc->benign_saddle_point) {
5689b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
5690b0f5fe93SStefano Zampini         } else {
5691b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
5692b0f5fe93SStefano Zampini         }
5693b0f5fe93SStefano Zampini       } else {
5694b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5695b0f5fe93SStefano Zampini       }
5696b0f5fe93SStefano Zampini     }
5697b0f5fe93SStefano Zampini     /* setup coarse ksp */
5698b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
5699cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
5700cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
57016e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
5702c8587f34SStefano Zampini       KSP       check_ksp;
57032b510759SStefano Zampini       KSPType   check_ksp_type;
5704c8587f34SStefano Zampini       PC        check_pc;
57056e683305SStefano Zampini       Vec       check_vec,coarse_vec;
57066a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
57072b510759SStefano Zampini       PetscInt  its;
57086e683305SStefano Zampini       PetscBool compute_eigs;
57096e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
57106e683305SStefano Zampini       PetscInt  neigs;
57118e185a42SStefano Zampini       const char *prefix;
5712c8587f34SStefano Zampini 
57132b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
57146e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
5715422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
571623ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5717f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
57182b510759SStefano Zampini       if (ispreonly) {
57192b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
57206e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
57212b510759SStefano Zampini       } else {
5722cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
57236e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
5724c8587f34SStefano Zampini       }
5725c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
57266e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
57276e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
57286e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
5729a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
5730a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
5731a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
5732a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
5733c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
5734c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
5735c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
5736c8587f34SStefano Zampini       /* create random vec */
57376e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
57386e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5739c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5740c8587f34SStefano Zampini       if (CoarseNullSpace) {
5741c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5742c8587f34SStefano Zampini       }
57436e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5744c8587f34SStefano Zampini       /* solve coarse problem */
57456e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5746c8587f34SStefano Zampini       if (CoarseNullSpace) {
57476e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5748c8587f34SStefano Zampini       }
5749cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
57506e683305SStefano Zampini       if (compute_eigs) {
5751854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5752854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
57536e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
57546e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
57556e683305SStefano Zampini         lambda_min = eigs_r[0];
57566e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
57576e683305SStefano Zampini           if (lambda_max>lambda_min) {
5758cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5759cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5760cbcc2c2aSStefano Zampini           }
5761c8587f34SStefano Zampini         }
5762c8587f34SStefano Zampini       }
5763cbcc2c2aSStefano Zampini 
5764c8587f34SStefano Zampini       /* check coarse problem residual error */
57656e683305SStefano Zampini       if (pcbddc->dbg_flag) {
57666e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
57676e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
57686e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5769c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
57706e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
57716e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5772c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5773779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
57746e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
57756e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
57766e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
57776e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5778b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
5779b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5780b0f5fe93SStefano Zampini         }
57816e683305SStefano Zampini         if (compute_eigs) {
57826e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
5783deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5784c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
57856e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
57866e683305SStefano 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);
57876e683305SStefano Zampini           for (i=0;i<neigs;i++) {
57886e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5789c8587f34SStefano Zampini           }
57906e683305SStefano Zampini         }
57916e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
57926e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
57936e683305SStefano Zampini       }
5794c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
57956e683305SStefano Zampini       if (compute_eigs) {
57966e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
57976e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5798c8587f34SStefano Zampini       }
57996e683305SStefano Zampini     }
58006e683305SStefano Zampini   }
5801cbcc2c2aSStefano Zampini   /* print additional info */
5802cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
58036e683305SStefano Zampini     /* waits until all processes reaches this point */
58046e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5805cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5806cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5807cbcc2c2aSStefano Zampini   }
5808cbcc2c2aSStefano Zampini 
58092b510759SStefano Zampini   /* free memory */
5810c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5811fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5812c8587f34SStefano Zampini   PetscFunctionReturn(0);
5813c8587f34SStefano Zampini }
5814674ae819SStefano Zampini 
5815f34684f1SStefano Zampini #undef __FUNCT__
5816f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5817f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5818f34684f1SStefano Zampini {
5819f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5820f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5821f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5822dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5823dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
582473be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5825dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5826f34684f1SStefano Zampini   PetscErrorCode ierr;
5827f34684f1SStefano Zampini 
5828f34684f1SStefano Zampini   PetscFunctionBegin;
5829f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
58300e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
58310e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5832727cdba6SStefano Zampini   }
5833dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
58343bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5835dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5836dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5837dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5838dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5839dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5840dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
58410e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
58420e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
58430e6343abSStefano Zampini   }
5844dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5845dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5846dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5847dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5848dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5849f34684f1SStefano Zampini 
5850f34684f1SStefano Zampini   /* check numbering */
5851f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5852019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5853dc456d91SStefano Zampini     PetscInt    i;
5854b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5855f34684f1SStefano Zampini 
5856f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5857f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5858f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
58591575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5860019a44ceSStefano Zampini     /* counter */
5861019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5862019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5863019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5864019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5865019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5866019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5867f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5868f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5869727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5870f34684f1SStefano Zampini     }
5871f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5872f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5873f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5874e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5875e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5876e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5877e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5878f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5879019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5880f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5881019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
588275c01103SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]);
588375c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
5884b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5885019a44ceSStefano 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);
5886f34684f1SStefano Zampini       }
5887f34684f1SStefano Zampini     }
5888019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5889b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5890f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5891f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5892f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5893f34684f1SStefano Zampini     }
5894f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5895f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5896e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5897e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5898f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5899f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5900b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5901ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5902ca8b9ea9SStefano Zampini 
5903ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
59043bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5905f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5906f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5907f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5908f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
59094bc2dc4bSStefano 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);
5910f34684f1SStefano Zampini       }
5911f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5912ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5913f34684f1SStefano Zampini     }
5914f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
59151575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5916302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5917f34684f1SStefano Zampini   }
59188bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5919f34684f1SStefano Zampini   /* get back data */
5920f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5921f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5922674ae819SStefano Zampini   PetscFunctionReturn(0);
5923674ae819SStefano Zampini }
5924674ae819SStefano Zampini 
5925e456f2a8SStefano Zampini #undef __FUNCT__
5926e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5927a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5928e456f2a8SStefano Zampini {
5929e456f2a8SStefano Zampini   IS             localis_t;
5930a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5931e456f2a8SStefano Zampini   PetscScalar    *vals;
5932e456f2a8SStefano Zampini   PetscErrorCode ierr;
5933e456f2a8SStefano Zampini 
5934e456f2a8SStefano Zampini   PetscFunctionBegin;
5935a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5936e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5937854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5938e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5939e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5940a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5941a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
59421035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5943a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
59441035eff8SStefano Zampini   }
5945a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5946e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5947e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5948a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5949a7dc3881SStefano Zampini   /* now compute set in local ordering */
5950a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5951a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5952a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5953a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5954a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5955ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5956e456f2a8SStefano Zampini       lsize++;
5957e456f2a8SStefano Zampini     }
5958e456f2a8SStefano Zampini   }
5959854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5960a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5961ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5962e456f2a8SStefano Zampini       idxs[lsize++] = i;
5963e456f2a8SStefano Zampini     }
5964e456f2a8SStefano Zampini   }
5965a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5966a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5967e456f2a8SStefano Zampini   *localis = localis_t;
5968e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5969e456f2a8SStefano Zampini }
5970906d46d4SStefano Zampini 
5971906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5972906d46d4SStefano Zampini #undef __FUNCT__
5973906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5974906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5975906d46d4SStefano Zampini {
5976906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5977906d46d4SStefano Zampini   PetscErrorCode   ierr;
5978906d46d4SStefano Zampini 
5979906d46d4SStefano Zampini   PetscFunctionBegin;
5980906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5981906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5982906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5983906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5984906d46d4SStefano Zampini   PetscFunctionReturn(0);
5985906d46d4SStefano Zampini }
5986906d46d4SStefano Zampini 
5987906d46d4SStefano Zampini #undef __FUNCT__
5988906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5989906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5990906d46d4SStefano Zampini {
5991906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5992906d46d4SStefano Zampini   PetscErrorCode   ierr;
5993906d46d4SStefano Zampini 
5994906d46d4SStefano Zampini   PetscFunctionBegin;
5995906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5996906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5997906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5998906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5999906d46d4SStefano Zampini   PetscFunctionReturn(0);
6000906d46d4SStefano Zampini }
6001b96c3477SStefano Zampini 
6002b96c3477SStefano Zampini #undef __FUNCT__
6003b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
600408122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6005b96c3477SStefano Zampini {
6006a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6007b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6008b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6009a64f4aa4SStefano Zampini   Mat                 S_j;
6010b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6011b96c3477SStefano Zampini   PetscBool           free_used_adj;
6012b96c3477SStefano Zampini   PetscErrorCode      ierr;
6013b96c3477SStefano Zampini 
6014b96c3477SStefano Zampini   PetscFunctionBegin;
6015b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6016b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
601708122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6018b96c3477SStefano Zampini     used_xadj = NULL;
6019b96c3477SStefano Zampini     used_adjncy = NULL;
6020b96c3477SStefano Zampini   } else {
602108122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
602208122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
602308122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
602408122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6025b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6026b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6027b96c3477SStefano Zampini     } else {
60282fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6029b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6030b96c3477SStefano Zampini       PetscInt       nvtxs;
6031b96c3477SStefano Zampini 
60322fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
60332fffb893SStefano Zampini       if (flg_row) {
6034b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6035b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6036b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6037b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
60382fffb893SStefano Zampini       } else {
60392fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
60402fffb893SStefano Zampini         used_xadj = NULL;
60412fffb893SStefano Zampini         used_adjncy = NULL;
60422fffb893SStefano Zampini       }
60432fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6044b96c3477SStefano Zampini     }
6045b96c3477SStefano Zampini   }
6046d5574798SStefano Zampini 
6047d5574798SStefano Zampini   /* setup sub_schurs data */
6048a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6049df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6050df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6051a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6052ca92afb2SStefano 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);
6053a64f4aa4SStefano Zampini   } else {
60546816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
605504708bb6SStefano Zampini     PetscBool isseqaij;
6056a3df083aSStefano Zampini     PetscInt  benign_n;
6057a3df083aSStefano Zampini 
60585feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
60595feab87aSStefano Zampini       PetscInt n_vertices;
60605feab87aSStefano Zampini 
60615feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
60622034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
60635feab87aSStefano Zampini     }
606404708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
606504708bb6SStefano Zampini     if (!isseqaij) {
606604708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
606704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
606804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
606904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
607004708bb6SStefano Zampini       } else {
607104708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
607204708bb6SStefano Zampini       }
607304708bb6SStefano Zampini     }
6074a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6075a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6076ca92afb2SStefano Zampini     } else {
6077a3df083aSStefano Zampini       benign_n = 0;
6078ca92afb2SStefano Zampini     }
6079a3df083aSStefano 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);
6080ca92afb2SStefano Zampini   }
6081d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6082b96c3477SStefano Zampini 
6083b96c3477SStefano Zampini   /* free adjacency */
6084b96c3477SStefano Zampini   if (free_used_adj) {
6085b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6086b96c3477SStefano Zampini   }
6087b96c3477SStefano Zampini   PetscFunctionReturn(0);
6088b96c3477SStefano Zampini }
6089b96c3477SStefano Zampini 
6090b96c3477SStefano Zampini #undef __FUNCT__
6091b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
609208122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6093b96c3477SStefano Zampini {
6094b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6095b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6096b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6097b96c3477SStefano Zampini   PCBDDCGraph         graph;
6098b96c3477SStefano Zampini   PetscErrorCode      ierr;
6099b96c3477SStefano Zampini 
6100b96c3477SStefano Zampini   PetscFunctionBegin;
6101b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
610208122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
61033301b35fSStefano Zampini     IS       verticesIS,verticescomm;
61043301b35fSStefano Zampini     PetscInt vsize,*idxs;
6105b96c3477SStefano Zampini 
6106b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
61073301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
61083301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
61093301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
61103301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
61113301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6112b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
61137fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
61143301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
61153301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6116b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6117b96c3477SStefano Zampini /*
6118b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
6119b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6120b96c3477SStefano Zampini     }
6121b96c3477SStefano Zampini */
6122b96c3477SStefano Zampini   } else {
6123b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6124b96c3477SStefano Zampini   }
6125b96c3477SStefano Zampini 
6126b96c3477SStefano Zampini   /* sub_schurs init */
6127a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6128a64f4aa4SStefano Zampini 
6129b96c3477SStefano Zampini   /* free graph struct */
613008122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6131b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6132b96c3477SStefano Zampini   }
6133b96c3477SStefano Zampini   PetscFunctionReturn(0);
6134b96c3477SStefano Zampini }
6135fa34dd3eSStefano Zampini 
6136fa34dd3eSStefano Zampini #undef __FUNCT__
6137fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6138fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6139fa34dd3eSStefano Zampini {
6140fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6141fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6142fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6143fa34dd3eSStefano Zampini 
6144fa34dd3eSStefano Zampini   PetscFunctionBegin;
6145fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6146fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
61474f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6148fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
61494f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
615075c01103SStefano Zampini     PetscReal      norm;
6151fa34dd3eSStefano Zampini     PetscInt       i;
6152fa34dd3eSStefano Zampini 
6153fa34dd3eSStefano Zampini     /* B0 and B0_B */
6154fa34dd3eSStefano Zampini     if (zerodiag) {
6155fa34dd3eSStefano Zampini       IS       dummy;
6156fa34dd3eSStefano Zampini 
61574f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
61584f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6159fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6160fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6161fa34dd3eSStefano Zampini     }
6162fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6163fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6164fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6165fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6166fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6167fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6168fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6169fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6170fa34dd3eSStefano Zampini     /* S_j */
6171fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6172fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6173fa34dd3eSStefano Zampini 
6174fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6175fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6176fa34dd3eSStefano Zampini     /* continuous in primal space */
6177fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6178fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6179fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6180fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
61814f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
61824f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6183fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6184fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6185fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6186fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6187fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6188fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6189fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6190fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6191fa34dd3eSStefano Zampini 
6192fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6193fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6194fa34dd3eSStefano Zampini     /* local with Schur */
6195fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6196fa34dd3eSStefano Zampini     if (zerodiag) {
6197fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
61984f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6199fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6200fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6201fa34dd3eSStefano Zampini     }
6202fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6203fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6204fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6205fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6206fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6207fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6208fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6209fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6210fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6211fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6212fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6213fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6214fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6215fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6216fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6217fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6218fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6219fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6220fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6221fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6222fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6223fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6224fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6225fa34dd3eSStefano Zampini     if (zerodiag) {
6226fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6227fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
62284f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6229fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6230fa34dd3eSStefano Zampini     }
6231fa34dd3eSStefano Zampini     /* BDDC */
6232fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6233fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6234fa34dd3eSStefano Zampini 
6235fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6236fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6237fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6238fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
62394f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
62404f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6241fa34dd3eSStefano Zampini     }
62424f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6243fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6244fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6245fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6246fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6247fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6248fa34dd3eSStefano Zampini   }
6249fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6250fa34dd3eSStefano Zampini }
6251