xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 1f4df5f7950cd01c3e9fc0b233e7a06004e4d6c1)
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>
5daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
6674ae819SStefano Zampini 
7a3df083aSStefano Zampini #undef __FUNCT__
8*1f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
9*1f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
10*1f4df5f7SStefano Zampini {
11*1f4df5f7SStefano Zampini   PetscErrorCode ierr;
12*1f4df5f7SStefano Zampini   Vec            local,global;
13*1f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
14*1f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
15*1f4df5f7SStefano Zampini 
16*1f4df5f7SStefano Zampini   PetscFunctionBegin;
17*1f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
18*1f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
19*1f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
20*1f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
21*1f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
22*1f4df5f7SStefano Zampini       PetscInt i;
23*1f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
24*1f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
25*1f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
26*1f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
27*1f4df5f7SStefano Zampini       }
28*1f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
29*1f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
30*1f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
31*1f4df5f7SStefano Zampini     }
32*1f4df5f7SStefano Zampini   } else {
33*1f4df5f7SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
34*1f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
35*1f4df5f7SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
36*1f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
37*1f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
38*1f4df5f7SStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
39*1f4df5f7SStefano Zampini       }
40*1f4df5f7SStefano Zampini     }
41*1f4df5f7SStefano Zampini   }
42*1f4df5f7SStefano Zampini 
43*1f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
44*1f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
45*1f4df5f7SStefano Zampini   }
46*1f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
47*1f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
48*1f4df5f7SStefano Zampini   }
49*1f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
50*1f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
51*1f4df5f7SStefano Zampini   }
52*1f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
53*1f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
54*1f4df5f7SStefano Zampini   PetscFunctionReturn(0);
55*1f4df5f7SStefano Zampini }
56*1f4df5f7SStefano Zampini 
57*1f4df5f7SStefano Zampini #undef __FUNCT__
58a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
59a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
60a3df083aSStefano Zampini {
61a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
62a3df083aSStefano Zampini   PetscErrorCode          ierr;
63a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
64a3df083aSStefano Zampini 
65a3df083aSStefano Zampini   PetscFunctionBegin;
66a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
67a3df083aSStefano Zampini   if (transpose) {
68a3df083aSStefano Zampini     apply_right = ctx->apply_left;
69a3df083aSStefano Zampini     apply_left = ctx->apply_right;
70a3df083aSStefano Zampini   } else {
71a3df083aSStefano Zampini     apply_right = ctx->apply_right;
72a3df083aSStefano Zampini     apply_left = ctx->apply_left;
73a3df083aSStefano Zampini   }
74a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
75a3df083aSStefano Zampini   if (apply_right) {
76a3df083aSStefano Zampini     const PetscScalar *ax;
77a3df083aSStefano Zampini     PetscInt          nl,i;
78a3df083aSStefano Zampini 
79a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
80a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
81a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
82a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
83a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
84a3df083aSStefano Zampini       PetscScalar    sum,val;
85a3df083aSStefano Zampini       const PetscInt *idxs;
86a3df083aSStefano Zampini       PetscInt       nz,j;
87a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
88a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
89a3df083aSStefano Zampini       sum = 0.;
90a3df083aSStefano Zampini       if (ctx->apply_p0) {
91a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
92a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
93a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
94a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
95a3df083aSStefano Zampini         }
96a3df083aSStefano Zampini       } else {
97a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
98a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
99a3df083aSStefano Zampini         }
100a3df083aSStefano Zampini       }
101a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
102a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
103a3df083aSStefano Zampini     }
104a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
105a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
106a3df083aSStefano Zampini   }
107a3df083aSStefano Zampini   if (transpose) {
108a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
109a3df083aSStefano Zampini   } else {
110a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
111a3df083aSStefano Zampini   }
112a3df083aSStefano Zampini   if (reset_x) {
113a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
114a3df083aSStefano Zampini   }
115a3df083aSStefano Zampini   if (apply_left) {
116a3df083aSStefano Zampini     PetscScalar *ay;
117a3df083aSStefano Zampini     PetscInt    i;
118a3df083aSStefano Zampini 
119a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
120a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
121a3df083aSStefano Zampini       PetscScalar    sum,val;
122a3df083aSStefano Zampini       const PetscInt *idxs;
123a3df083aSStefano Zampini       PetscInt       nz,j;
124a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
125a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
126a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
127a3df083aSStefano Zampini       if (ctx->apply_p0) {
128a3df083aSStefano Zampini         sum = 0.;
129a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
130a3df083aSStefano Zampini           sum += ay[idxs[j]];
131a3df083aSStefano Zampini           ay[idxs[j]] += val;
132a3df083aSStefano Zampini         }
133a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
134a3df083aSStefano Zampini       } else {
135a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
136a3df083aSStefano Zampini           ay[idxs[j]] += val;
137a3df083aSStefano Zampini         }
138a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
139a3df083aSStefano Zampini       }
140a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
141a3df083aSStefano Zampini     }
142a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
143a3df083aSStefano Zampini   }
144a3df083aSStefano Zampini   PetscFunctionReturn(0);
145a3df083aSStefano Zampini }
146a3df083aSStefano Zampini 
147a3df083aSStefano Zampini #undef __FUNCT__
148a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
149a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
150a3df083aSStefano Zampini {
151a3df083aSStefano Zampini   PetscErrorCode ierr;
152a3df083aSStefano Zampini 
153a3df083aSStefano Zampini   PetscFunctionBegin;
154a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
155a3df083aSStefano Zampini   PetscFunctionReturn(0);
156a3df083aSStefano Zampini }
157a3df083aSStefano Zampini 
158a3df083aSStefano Zampini #undef __FUNCT__
159a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
160a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
161a3df083aSStefano Zampini {
162a3df083aSStefano Zampini   PetscErrorCode ierr;
163a3df083aSStefano Zampini 
164a3df083aSStefano Zampini   PetscFunctionBegin;
165a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
166a3df083aSStefano Zampini   PetscFunctionReturn(0);
167a3df083aSStefano Zampini }
168a3df083aSStefano Zampini 
169a3df083aSStefano Zampini #undef __FUNCT__
170a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
171a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
172a3df083aSStefano Zampini {
173a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
174a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
175a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
176a3df083aSStefano Zampini   PetscErrorCode          ierr;
177a3df083aSStefano Zampini 
178a3df083aSStefano Zampini   PetscFunctionBegin;
179a3df083aSStefano Zampini   if (!restore) {
1801dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
181a3df083aSStefano Zampini     PetscScalar        *work;
182df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs->reuse_solver;
183a3df083aSStefano Zampini 
1841dd7afcfSStefano Zampini     if (pcbddc->benign_original_mat) {
1851dd7afcfSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
1861dd7afcfSStefano Zampini     }
1871dd7afcfSStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) {
1881dd7afcfSStefano Zampini       PetscFunctionReturn(0);
1891dd7afcfSStefano Zampini     }
190a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
191a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
192a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
193a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
194a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
195a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
196a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
197a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
198a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
199a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
200a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
201a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
202059032f7SStefano Zampini     if (reuse) {
203a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
2041dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
205059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
206059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
207059032f7SStefano Zampini       PetscInt               i;
208059032f7SStefano Zampini 
209059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
210059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
211059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
212059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
213059032f7SStefano Zampini       }
214059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
2151dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
216059032f7SStefano Zampini     }
217a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
218a3df083aSStefano Zampini     ctx->work = work;
219a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
220a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
221a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
222a3df083aSStefano Zampini     pcis->A_IB = A_IB;
223a3df083aSStefano Zampini 
224a3df083aSStefano Zampini     /* A_BI as A_IB^T */
225a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
226a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
227a3df083aSStefano Zampini     pcis->A_BI = A_BI;
228a3df083aSStefano Zampini   } else {
2291dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
2301dd7afcfSStefano Zampini       PetscFunctionReturn(0);
2311dd7afcfSStefano Zampini     }
232a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
233a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
234a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
2351dd7afcfSStefano Zampini     ctx->A = NULL;
2361dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
2371dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
2381dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
2391dd7afcfSStefano Zampini     if (ctx->free) {
240059032f7SStefano Zampini       PetscInt i;
2411dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
242059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
243059032f7SStefano Zampini       }
244059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
245059032f7SStefano Zampini     }
246a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
247a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
248a3df083aSStefano Zampini   }
249a3df083aSStefano Zampini   PetscFunctionReturn(0);
250a3df083aSStefano Zampini }
251a3df083aSStefano Zampini 
252a3df083aSStefano Zampini /* used just in bddc debug mode */
253a3df083aSStefano Zampini #undef __FUNCT__
254a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
255a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
256a3df083aSStefano Zampini {
257a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
258a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
259a3df083aSStefano Zampini   Mat            An;
260a3df083aSStefano Zampini   PetscErrorCode ierr;
261a3df083aSStefano Zampini 
262a3df083aSStefano Zampini   PetscFunctionBegin;
263a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
264a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
265a3df083aSStefano Zampini   if (is1) {
266a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
267a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
268a3df083aSStefano Zampini   } else {
269a3df083aSStefano Zampini     *B = An;
270a3df083aSStefano Zampini   }
271a3df083aSStefano Zampini   PetscFunctionReturn(0);
272a3df083aSStefano Zampini }
273a3df083aSStefano Zampini 
2741cf9b237SStefano Zampini /* TODO: add reuse flag */
2751cf9b237SStefano Zampini #undef __FUNCT__
2761cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
2771cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
2781cf9b237SStefano Zampini {
2791cf9b237SStefano Zampini   Mat            Bt;
2801cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
2811cf9b237SStefano Zampini   const PetscInt *ii,*ij;
2821cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
2831cf9b237SStefano Zampini   PetscBool      flg_row;
2841cf9b237SStefano Zampini   PetscErrorCode ierr;
2851cf9b237SStefano Zampini 
2861cf9b237SStefano Zampini   PetscFunctionBegin;
2871cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
2881cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
2891cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
2901cf9b237SStefano Zampini   nnz = n;
2911cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
2921cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
2931cf9b237SStefano Zampini   }
2941cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
2951cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
2961cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
2971cf9b237SStefano Zampini   nnz = 0;
2981cf9b237SStefano Zampini   bii[0] = 0;
2991cf9b237SStefano Zampini   for (i=0;i<n;i++) {
3001cf9b237SStefano Zampini     PetscInt j;
3011cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
3021cf9b237SStefano Zampini       PetscScalar entry = a[j];
3031cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
3041cf9b237SStefano Zampini         bij[nnz] = ij[j];
3051cf9b237SStefano Zampini         bdata[nnz] = entry;
3061cf9b237SStefano Zampini         nnz++;
3071cf9b237SStefano Zampini       }
3081cf9b237SStefano Zampini     }
3091cf9b237SStefano Zampini     bii[i+1] = nnz;
3101cf9b237SStefano Zampini   }
3111cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
3121cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
3131cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
3141cf9b237SStefano Zampini   {
3151cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
3161cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
3171cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
3181cf9b237SStefano Zampini   }
3191cf9b237SStefano Zampini   *B = Bt;
3201cf9b237SStefano Zampini   PetscFunctionReturn(0);
3211cf9b237SStefano Zampini }
3221cf9b237SStefano Zampini 
323674ae819SStefano Zampini #undef __FUNCT__
3244f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
3254f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
3264f1b2e48SStefano Zampini {
3274f1b2e48SStefano Zampini   Mat                    B;
3284f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
3294f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
3304f1b2e48SStefano Zampini   PCBDDCGraph            graph;
3314f1b2e48SStefano Zampini   PetscInt               i,n;
3324f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
3334f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
3344f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
3354f1b2e48SStefano Zampini   PetscErrorCode         ierr;
3364f1b2e48SStefano Zampini 
3374f1b2e48SStefano Zampini   PetscFunctionBegin;
33863c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
33963c961adSStefano Zampini     *ncc = 0;
34063c961adSStefano Zampini     *cc = NULL;
34163c961adSStefano Zampini     PetscFunctionReturn(0);
34263c961adSStefano Zampini   }
3434f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
3444f1b2e48SStefano Zampini   if (!isseqaij && filter) {
3451cf9b237SStefano Zampini     PetscBool isseqdense;
3461cf9b237SStefano Zampini 
3471cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
3481cf9b237SStefano Zampini     if (!isseqdense) {
3494f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
3501cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
3511cf9b237SStefano Zampini       PetscScalar *array;
3521cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
3531cf9b237SStefano Zampini 
3541cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
3551cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
3561cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
3571cf9b237SStefano Zampini       for (i=0;i<n;i++) {
3581cf9b237SStefano Zampini         PetscInt j;
3591cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
3601cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
3611cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
3621cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
3631cf9b237SStefano Zampini         }
3641cf9b237SStefano Zampini       }
3651cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
3669d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
3671cf9b237SStefano Zampini     }
3684f1b2e48SStefano Zampini   } else {
3694f1b2e48SStefano Zampini     B = A;
3704f1b2e48SStefano Zampini   }
3714f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3724f1b2e48SStefano Zampini 
3734f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
3744f1b2e48SStefano Zampini   if (filter) {
3754f1b2e48SStefano Zampini     PetscScalar *data;
3764f1b2e48SStefano Zampini     PetscInt    j,cum;
3774f1b2e48SStefano Zampini 
3784f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
3794f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
3804f1b2e48SStefano Zampini     cum = 0;
3814f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
3824f1b2e48SStefano Zampini       PetscInt t;
3834f1b2e48SStefano Zampini 
3844f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
3854f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
3864f1b2e48SStefano Zampini           continue;
3874f1b2e48SStefano Zampini         }
3884f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
3894f1b2e48SStefano Zampini       }
3904f1b2e48SStefano Zampini       t = xadj_filtered[i];
3914f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
3924f1b2e48SStefano Zampini       cum += t;
3934f1b2e48SStefano Zampini     }
3944f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
3954f1b2e48SStefano Zampini   } else {
3964f1b2e48SStefano Zampini     xadj_filtered = NULL;
3974f1b2e48SStefano Zampini     adjncy_filtered = NULL;
3984f1b2e48SStefano Zampini   }
3994f1b2e48SStefano Zampini 
4004f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
4014f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
4024f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
4034f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4044f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
4054f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
4064f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
4074f1b2e48SStefano Zampini   if (xadj_filtered) {
4084f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
4094f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
4104f1b2e48SStefano Zampini   } else {
4114f1b2e48SStefano Zampini     graph->xadj = xadj;
4124f1b2e48SStefano Zampini     graph->adjncy = adjncy;
4134f1b2e48SStefano Zampini   }
4144f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
4154f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4164f1b2e48SStefano Zampini   /* partial clean up */
4174f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
4184f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4191cf9b237SStefano Zampini   if (A != B) {
4204f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
4214f1b2e48SStefano Zampini   }
4224f1b2e48SStefano Zampini 
4234f1b2e48SStefano Zampini   /* get back data */
4241cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
4251cf9b237SStefano Zampini   if (cc) {
4264f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
4274f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
4284f1b2e48SStefano 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);
4294f1b2e48SStefano Zampini     }
4304f1b2e48SStefano Zampini     *cc = cc_n;
4311cf9b237SStefano Zampini   }
4324f1b2e48SStefano Zampini   /* clean up graph */
4334f1b2e48SStefano Zampini   graph->xadj = 0;
4344f1b2e48SStefano Zampini   graph->adjncy = 0;
4354f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
4364f1b2e48SStefano Zampini   PetscFunctionReturn(0);
4374f1b2e48SStefano Zampini }
4384f1b2e48SStefano Zampini 
4394f1b2e48SStefano Zampini #undef __FUNCT__
4405408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
4415408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
4425408967cSStefano Zampini {
4435408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4445408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
445dee84bffSStefano Zampini   IS             dirIS = NULL;
4464f1b2e48SStefano Zampini   PetscInt       i;
4475408967cSStefano Zampini   PetscErrorCode ierr;
4485408967cSStefano Zampini 
4495408967cSStefano Zampini   PetscFunctionBegin;
450dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
4515408967cSStefano Zampini   if (zerodiag) {
4525408967cSStefano Zampini     Mat            A;
4535408967cSStefano Zampini     Vec            vec3_N;
4545408967cSStefano Zampini     PetscScalar    *vals;
4555408967cSStefano Zampini     const PetscInt *idxs;
456d12d3064SStefano Zampini     PetscInt       nz,*count;
4575408967cSStefano Zampini 
4585408967cSStefano Zampini     /* p0 */
4595408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
4605408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
4615408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
4625408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
4634f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
4645408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4655408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4665408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4675408967cSStefano Zampini     /* v_I */
4685408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
4695408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
4705408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4715408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
4725408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
4735408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
4745408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4755408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
4765408967cSStefano Zampini     if (dirIS) {
4775408967cSStefano Zampini       PetscInt n;
4785408967cSStefano Zampini 
4795408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
4805408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
4815408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
4825408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
4835408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
4845408967cSStefano Zampini     }
4855408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
4865408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
4875408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
4885408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
4895408967cSStefano Zampini     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
4905408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
4915408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
492fbfcb133SStefano Zampini     if (PetscAbsScalar(vals[0]) > 1.e-1) {
493b9b0e38cSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! b(v_I,p_0) = %1.6e (should be numerically 0.)",PetscAbsScalar(vals[0]));
4945408967cSStefano Zampini     }
4955408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
4965408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
497d12d3064SStefano Zampini 
498d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
499d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
500d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
501d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
502d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
503d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
504d4d8cf7bSStefano Zampini     for (i=0;i<nz;i++) {
505d12d3064SStefano Zampini       if (count[idxs[i]]) {
506d12d3064SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
507d12d3064SStefano Zampini       }
508d4d8cf7bSStefano Zampini     }
509d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
510d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
5115408967cSStefano Zampini   }
512dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
5135408967cSStefano Zampini 
5145408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
5155408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
5164f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
5175408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
5184f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
5195408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
5204f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
5214f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
5224f1b2e48SStefano 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);
5234f1b2e48SStefano Zampini     }
5245408967cSStefano Zampini   }
5255408967cSStefano Zampini   PetscFunctionReturn(0);
5265408967cSStefano Zampini }
5275408967cSStefano Zampini 
5285408967cSStefano Zampini #undef __FUNCT__
529339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
530339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
531339f8db1SStefano Zampini {
532339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5334f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
534b0f5fe93SStefano Zampini   PetscInt       nz,n;
535*1f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
5364f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
537339f8db1SStefano Zampini   PetscErrorCode ierr;
538339f8db1SStefano Zampini 
539339f8db1SStefano Zampini   PetscFunctionBegin;
5409f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
5419f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
542a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
543a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
544a3df083aSStefano Zampini   }
545a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
546a3df083aSStefano Zampini   pcbddc->benign_n = 0;
5474f1b2e48SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
5484f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
5494f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
5504f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
5514f1b2e48SStefano Zampini      since the local Schur complements are SPD
5524f1b2e48SStefano Zampini   */
5534f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
5544f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
55540fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
5564f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
5574f1b2e48SStefano Zampini 
5584f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
5594f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
5604f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
5614f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
562ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
56340fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
56440fa8d13SStefano Zampini     if (!sorted) {
56540fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
56640fa8d13SStefano Zampini     }
56740fa8d13SStefano Zampini   } else {
56840fa8d13SStefano Zampini     pressures = NULL;
56940fa8d13SStefano Zampini   }
57097d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
57197d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
57227b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
57397d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
574339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
575339f8db1SStefano Zampini   if (!sorted) {
576339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
577339f8db1SStefano Zampini   }
578339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5794f1b2e48SStefano Zampini   if (!nz) {
5804f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
5814f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
58240fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
58340fa8d13SStefano Zampini   }
5844f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
5854f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
5864f1b2e48SStefano Zampini   zerodiag_subs = NULL;
5874f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
588*1f4df5f7SStefano Zampini   n_interior_dofs = 0;
589*1f4df5f7SStefano Zampini   interior_dofs = NULL;
590*1f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
591*1f4df5f7SStefano Zampini     PetscInt n,i,j;
592*1f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
593*1f4df5f7SStefano Zampini     PetscInt *iwork;
594*1f4df5f7SStefano Zampini 
595*1f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
596*1f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
597*1f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
598*1f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
599*1f4df5f7SStefano Zampini     for (i=0;i<n_neigh;i++)
600*1f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
601*1f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
602*1f4df5f7SStefano Zampini     for (i=0;i<n;i++)
603*1f4df5f7SStefano Zampini       if (!iwork[i])
604*1f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
605*1f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
606*1f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
607*1f4df5f7SStefano Zampini   }
6084f1b2e48SStefano Zampini   if (has_null_pressures) {
6094f1b2e48SStefano Zampini     IS             *subs;
610*1f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
611*1f4df5f7SStefano Zampini     const PetscInt *idxs;
612*1f4df5f7SStefano Zampini     PetscScalar    *array;
613*1f4df5f7SStefano Zampini     Vec            *work;
614*1f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
6154f1b2e48SStefano Zampini 
6164f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
6174f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
618*1f4df5f7SStefano Zampini     /* these vectors are needed to check if the constant on pressures is in the kernel of the local operator B (i.e. B(v_I,p0) should be zero) */
619*1f4df5f7SStefano Zampini     if (pcbddc->current_level) {
620*1f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
621*1f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
622*1f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
623*1f4df5f7SStefano Zampini       /* work[0] = 1_p */
624*1f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
625*1f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
626*1f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
627*1f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
628*1f4df5f7SStefano Zampini       /* work[0] = 1_v */
629*1f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
630*1f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
631*1f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
632*1f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
633*1f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
634*1f4df5f7SStefano Zampini     }
6354f1b2e48SStefano Zampini     if (nsubs > 1) {
6364f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
6374f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
6384f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
6394f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
6404f1b2e48SStefano Zampini         PetscInt               nl;
6414f1b2e48SStefano Zampini 
6424f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
6434f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
6444f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
6454f1b2e48SStefano Zampini         if (nl) {
6464f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
6474f1b2e48SStefano Zampini 
648*1f4df5f7SStefano Zampini           if (pcbddc->current_level) {
649*1f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
650*1f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
651*1f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
652*1f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
653*1f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
654*1f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
655*1f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
656*1f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
657*1f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
658*1f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
659*1f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
660*1f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
661*1f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
662*1f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
663*1f4df5f7SStefano Zampini                 break;
664*1f4df5f7SStefano Zampini               }
665*1f4df5f7SStefano Zampini             }
666*1f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
667*1f4df5f7SStefano Zampini           }
668*1f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
669*1f4df5f7SStefano Zampini             IS       t_bc;
670*1f4df5f7SStefano Zampini             PetscInt nzb;
671*1f4df5f7SStefano Zampini 
672*1f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
673*1f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
674*1f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
675*1f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
676*1f4df5f7SStefano Zampini           }
677*1f4df5f7SStefano Zampini           if (valid && pressures) {
6784f1b2e48SStefano Zampini             IS t_pressure_subs;
6794f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
6804f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
6814f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
6824f1b2e48SStefano Zampini           }
6834f1b2e48SStefano Zampini           if (valid) {
6844f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
6854f1b2e48SStefano Zampini             pcbddc->benign_n++;
6864f1b2e48SStefano Zampini           } else {
6874f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
6884f1b2e48SStefano Zampini           }
6894f1b2e48SStefano Zampini         }
6904f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
6914f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
6924f1b2e48SStefano Zampini       }
6934f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
6944f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
695*1f4df5f7SStefano Zampini 
696*1f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
697*1f4df5f7SStefano Zampini         PetscInt nzb;
698*1f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
699*1f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
700*1f4df5f7SStefano Zampini       }
701*1f4df5f7SStefano Zampini       if (valid && pressures) {
7024f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
7034f1b2e48SStefano Zampini       }
704*1f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
705*1f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
706*1f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
707*1f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
708*1f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
709*1f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
710*1f4df5f7SStefano Zampini               valid = PETSC_FALSE;
711*1f4df5f7SStefano Zampini               break;
712*1f4df5f7SStefano Zampini           }
713*1f4df5f7SStefano Zampini         }
714*1f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
715*1f4df5f7SStefano Zampini       }
7164f1b2e48SStefano Zampini       if (valid) {
7174f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
718ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
7194f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
7204f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
7214f1b2e48SStefano Zampini       }
7224f1b2e48SStefano Zampini     }
723*1f4df5f7SStefano Zampini     if (pcbddc->current_level) {
724*1f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
7254f1b2e48SStefano Zampini     }
726*1f4df5f7SStefano Zampini   }
727*1f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
7284f1b2e48SStefano Zampini 
7294f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
730b9b0e38cSStefano Zampini     PetscInt n;
731b9b0e38cSStefano Zampini 
7324f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
7334f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
734b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
735b9b0e38cSStefano Zampini     if (n) {
7364f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
7374f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
7384f1b2e48SStefano Zampini     }
739b9b0e38cSStefano Zampini   }
7404f1b2e48SStefano Zampini 
7414f1b2e48SStefano Zampini   /* final check for null pressures */
7424f1b2e48SStefano Zampini   if (zerodiag && pressures) {
7434f1b2e48SStefano Zampini     PetscInt nz,np;
7444f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
7454f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
7464f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
7474f1b2e48SStefano Zampini   }
7484f1b2e48SStefano Zampini 
7494f1b2e48SStefano Zampini   if (recompute_zerodiag) {
7504f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
7514f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
7524f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
7534f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
7544f1b2e48SStefano Zampini     } else {
7554f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
7564f1b2e48SStefano Zampini 
7574f1b2e48SStefano Zampini       nzn = 0;
7584f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
7594f1b2e48SStefano Zampini         PetscInt ns;
7604f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
7614f1b2e48SStefano Zampini         nzn += ns;
7624f1b2e48SStefano Zampini       }
7634f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
7644f1b2e48SStefano Zampini       nzn = 0;
7654f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
7664f1b2e48SStefano Zampini         PetscInt ns,*idxs;
7674f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
7684f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
7694f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
7704f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
7714f1b2e48SStefano Zampini         nzn += ns;
7724f1b2e48SStefano Zampini       }
7734f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
7744f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
7754f1b2e48SStefano Zampini     }
7764f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
7774f1b2e48SStefano Zampini   }
7784f1b2e48SStefano Zampini 
779b3afcdbeSStefano Zampini   /* no-net-flux */
780b3afcdbeSStefano Zampini   if (pcbddc->benign_compute_nonetflux) {
781b3afcdbeSStefano Zampini     Mat_IS*                matis = (Mat_IS*)(pc->pmat->data);
782b3afcdbeSStefano Zampini     MatNullSpace           near_null_space;
783b3afcdbeSStefano Zampini     ISLocalToGlobalMapping rmap;
784b3afcdbeSStefano Zampini     Vec                    quad_vec;
785b3afcdbeSStefano Zampini     PetscScalar            *pvals;
786b3afcdbeSStefano Zampini     PetscInt               i,np,*dummyins;
787*1f4df5f7SStefano Zampini     IS                     isused = NULL;
788*1f4df5f7SStefano Zampini     PetscBool              participate = PETSC_TRUE;
789b3afcdbeSStefano Zampini 
790b3afcdbeSStefano Zampini     /* create vector to hold quadrature weights */
791b3afcdbeSStefano Zampini     ierr = MatCreateVecs(pc->pmat,&quad_vec,NULL);CHKERRQ(ierr);
792b3afcdbeSStefano Zampini     ierr = VecSet(quad_vec,0.0);CHKERRQ(ierr);
793b3afcdbeSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&rmap,NULL);CHKERRQ(ierr);
794b3afcdbeSStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vec,rmap);CHKERRQ(ierr);
795b3afcdbeSStefano Zampini 
796b3afcdbeSStefano Zampini     /* compute B^{(i)T} * 1_p */
797b3afcdbeSStefano Zampini     np = 0;
798*1f4df5f7SStefano Zampini     if (pressures) {
799*1f4df5f7SStefano Zampini       isused = pressures;
800*1f4df5f7SStefano Zampini     } else {
801*1f4df5f7SStefano Zampini       isused = zerodiag;
802*1f4df5f7SStefano Zampini     }
803*1f4df5f7SStefano Zampini     if (isused) {
804*1f4df5f7SStefano Zampini       ierr = ISGetLocalSize(isused,&np);CHKERRQ(ierr);
805b3afcdbeSStefano Zampini     }
806b3afcdbeSStefano Zampini     ierr = PetscMalloc1(np,&pvals);CHKERRQ(ierr);
807b3afcdbeSStefano Zampini     for (i=0;i<np;i++) pvals[i] = 1.;
808b3afcdbeSStefano Zampini     ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
809b3afcdbeSStefano Zampini     if (np) {
810b3afcdbeSStefano Zampini       const PetscInt *pidxs;
811b3afcdbeSStefano Zampini 
812*1f4df5f7SStefano Zampini       if (isused) {
813*1f4df5f7SStefano Zampini         ierr = ISGetIndices(isused,&pidxs);CHKERRQ(ierr);
814b3afcdbeSStefano Zampini       }
815b3afcdbeSStefano Zampini       ierr = VecSetValues(matis->x,np,pidxs,pvals,INSERT_VALUES);CHKERRQ(ierr);
816*1f4df5f7SStefano Zampini       if (isused) {
817*1f4df5f7SStefano Zampini         ierr = ISRestoreIndices(isused,&pidxs);CHKERRQ(ierr);
818b3afcdbeSStefano Zampini       }
819b3afcdbeSStefano Zampini     }
820b3afcdbeSStefano Zampini     ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
821b3afcdbeSStefano Zampini     ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
822b3afcdbeSStefano Zampini     ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
823b3afcdbeSStefano Zampini     ierr = PetscFree(pvals);CHKERRQ(ierr);
824*1f4df5f7SStefano Zampini     if (!isused) participate = PETSC_FALSE;
825b3afcdbeSStefano Zampini     /* decide which of the sharing ranks (per dof) has to insert the values (should just be a matter of having a different orientation) */
826b3afcdbeSStefano Zampini     ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
827daf8a457SStefano Zampini     for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = -1;
828*1f4df5f7SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++)
829*1f4df5f7SStefano Zampini       if (participate) matis->sf_leafdata[i] = PetscGlobalRank;
830*1f4df5f7SStefano Zampini       else  matis->sf_leafdata[i] = -1;
831*1f4df5f7SStefano Zampini 
832b3afcdbeSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_MAX);CHKERRQ(ierr);
833b3afcdbeSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_MAX);CHKERRQ(ierr);
834b3afcdbeSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
835b3afcdbeSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
836b3afcdbeSStefano Zampini     ierr = VecGetArray(matis->y,&pvals);CHKERRQ(ierr);
837daf8a457SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++) {
838b3afcdbeSStefano Zampini       if (PetscGlobalRank != matis->sf_leafdata[i]) {
839b3afcdbeSStefano Zampini         pvals[i] = 0.;
840b3afcdbeSStefano Zampini       }
841b3afcdbeSStefano Zampini     }
842daf8a457SStefano Zampini     ierr = PetscMalloc1(matis->sf->nleaves,&dummyins);CHKERRQ(ierr);
843daf8a457SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++) dummyins[i] = i;
844daf8a457SStefano Zampini     ierr = VecSetValuesLocal(quad_vec,matis->sf->nleaves,dummyins,pvals,ADD_VALUES);CHKERRQ(ierr);
845b3afcdbeSStefano Zampini     ierr = VecRestoreArray(matis->y,&pvals);CHKERRQ(ierr);
846b3afcdbeSStefano Zampini     ierr = PetscFree(dummyins);CHKERRQ(ierr);
847b3afcdbeSStefano Zampini 
848b3afcdbeSStefano Zampini     /* assembly quadrature vec and attach near null space to pmat */
849b3afcdbeSStefano Zampini     ierr = VecAssemblyBegin(quad_vec);CHKERRQ(ierr);
850b3afcdbeSStefano Zampini     ierr = VecAssemblyEnd(quad_vec);CHKERRQ(ierr);
851b3afcdbeSStefano Zampini     ierr = VecNormalize(quad_vec,NULL);CHKERRQ(ierr);
852b3afcdbeSStefano Zampini     ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,1,&quad_vec,&near_null_space);CHKERRQ(ierr);
853b3afcdbeSStefano Zampini     ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
854b3afcdbeSStefano Zampini     ierr = MatSetNearNullSpace(pc->pmat,near_null_space);CHKERRQ(ierr);
855b3afcdbeSStefano Zampini     ierr = MatNullSpaceDestroy(&near_null_space);CHKERRQ(ierr);
856b3afcdbeSStefano Zampini   }
857b3afcdbeSStefano Zampini 
858b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
8594f1b2e48SStefano Zampini   if (has_null_pressures) {
8604f1b2e48SStefano Zampini     IS             zerodiagc;
8614f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
8624f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
8634f1b2e48SStefano Zampini 
8644f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
865339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
866339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
867339f8db1SStefano Zampini     /* local change of basis for pressures */
868339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
86997d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
870339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
871339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
872339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
8734f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
8744f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
8754f1b2e48SStefano Zampini       PetscInt nzs,j;
8764f1b2e48SStefano Zampini 
8774f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
8784f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
8794f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
8804f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
8814f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
8824f1b2e48SStefano Zampini     }
883339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
884339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
885339f8db1SStefano Zampini     /* set identity on velocities */
886339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
887339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
888339f8db1SStefano Zampini     }
8894f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
8904f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
8919f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
8924f1b2e48SStefano 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);
893339f8db1SStefano Zampini     /* set change on pressures */
8944f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
8954f1b2e48SStefano Zampini       PetscScalar *array;
8964f1b2e48SStefano Zampini       PetscInt    nzs;
8974f1b2e48SStefano Zampini 
8984f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
8994f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
9004f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
901339f8db1SStefano Zampini         PetscScalar vals[2];
902339f8db1SStefano Zampini         PetscInt    cols[2];
903339f8db1SStefano Zampini 
904339f8db1SStefano Zampini         cols[0] = idxs[i];
9054f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
906339f8db1SStefano Zampini         vals[0] = 1.;
907b0f5fe93SStefano Zampini         vals[1] = 1.;
9084f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
909339f8db1SStefano Zampini       }
9104f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
9114f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
9124f1b2e48SStefano Zampini       array[nzs-1] = 1.;
9134f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
9144f1b2e48SStefano Zampini       /* store local idxs for p0 */
9154f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
9164f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
917339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
9184f1b2e48SStefano Zampini     }
919339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
920339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
921a3df083aSStefano Zampini     /* project if needed */
922a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
9231dd7afcfSStefano Zampini       Mat M;
9241dd7afcfSStefano Zampini 
9251dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
926339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
9271dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
9281dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
929a3df083aSStefano Zampini     }
9304f1b2e48SStefano Zampini     /* store global idxs for p0 */
9314f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
932339f8db1SStefano Zampini   }
933ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
9344f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
935b0f5fe93SStefano Zampini 
936b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
937b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
93827b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
93927b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
940339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
941339f8db1SStefano Zampini   PetscFunctionReturn(0);
942339f8db1SStefano Zampini }
943339f8db1SStefano Zampini 
944339f8db1SStefano Zampini #undef __FUNCT__
945015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
946015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
947efc2fbd9SStefano Zampini {
948efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
949de9d7bd0SStefano Zampini   PetscScalar    *array;
950efc2fbd9SStefano Zampini   PetscErrorCode ierr;
951efc2fbd9SStefano Zampini 
952efc2fbd9SStefano Zampini   PetscFunctionBegin;
953efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
954efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
9554f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
956efc2fbd9SStefano Zampini   }
957de9d7bd0SStefano Zampini   if (get) {
958efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
9594f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
9604f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
961efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
962de9d7bd0SStefano Zampini   } else {
963de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
964de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
965de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
966de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
967efc2fbd9SStefano Zampini   }
968efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
969efc2fbd9SStefano Zampini }
970efc2fbd9SStefano Zampini 
971efc2fbd9SStefano Zampini #undef __FUNCT__
972c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
973c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
974c263805aSStefano Zampini {
975c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
976c263805aSStefano Zampini   PetscErrorCode ierr;
977c263805aSStefano Zampini 
978c263805aSStefano Zampini   PetscFunctionBegin;
979c263805aSStefano Zampini   /* TODO: add error checking
980c263805aSStefano Zampini     - avoid nested pop (or push) calls.
981c263805aSStefano Zampini     - cannot push before pop.
9821c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
983c263805aSStefano Zampini   */
9844f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
985efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
986efc2fbd9SStefano Zampini   }
987c263805aSStefano Zampini   if (pop) {
988a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
9894f1b2e48SStefano Zampini       IS       is_p0;
9904f1b2e48SStefano Zampini       MatReuse reuse;
991c263805aSStefano Zampini 
992c263805aSStefano Zampini       /* extract B_0 */
9934f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
9944f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
9954f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
9964f1b2e48SStefano Zampini       }
9974f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
9984f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
999c263805aSStefano Zampini       /* remove rows and cols from local problem */
1000c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
100197d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
10024f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
10034f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
1004a3df083aSStefano Zampini     } else {
1005a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
1006a3df083aSStefano Zampini       PetscScalar *vals;
1007a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
1008a3df083aSStefano Zampini 
1009a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
1010a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
1011a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
10120b5adadeSStefano Zampini         PetscInt *nnz;
1013a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
1014a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
1015a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1016331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
1017331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
1018331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
1019331e053bSStefano Zampini           nnz[i] = n - nnz[i];
1020331e053bSStefano Zampini         }
1021331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
1022331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
1023331e053bSStefano Zampini       }
1024a3df083aSStefano Zampini 
1025a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1026a3df083aSStefano Zampini         PetscScalar *array;
1027a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
1028a3df083aSStefano Zampini 
1029a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
1030a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1031a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1032a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
1033a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1034a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
1035a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
1036a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
1037a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
1038a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
1039a3df083aSStefano Zampini         cum = 0;
1040a3df083aSStefano Zampini         for (j=0;j<n;j++) {
104122db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
1042a3df083aSStefano Zampini             vals[cum] = array[j];
1043a3df083aSStefano Zampini             idxs_ins[cum] = j;
1044a3df083aSStefano Zampini             cum++;
1045a3df083aSStefano Zampini           }
1046a3df083aSStefano Zampini         }
1047a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
1048a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
1049a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1050a3df083aSStefano Zampini       }
1051a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1052a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1053a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
1054a3df083aSStefano Zampini     }
1055c263805aSStefano Zampini   } else { /* push */
1056a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
10574f1b2e48SStefano Zampini       PetscInt i;
10584f1b2e48SStefano Zampini 
10594f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
10604f1b2e48SStefano Zampini         PetscScalar *B0_vals;
10614f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
10624f1b2e48SStefano Zampini 
10634f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
10644f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
10657b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
10664f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
10674f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
10684f1b2e48SStefano Zampini       }
1069c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1070c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1071a3df083aSStefano Zampini     } else {
1072a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
1073a3df083aSStefano Zampini     }
1074c263805aSStefano Zampini   }
1075c263805aSStefano Zampini   PetscFunctionReturn(0);
1076c263805aSStefano Zampini }
1077c263805aSStefano Zampini 
1078c263805aSStefano Zampini #undef __FUNCT__
1079b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
108008122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
1081b1b3d7a2SStefano Zampini {
1082b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
108308122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
108408122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
108508122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
108608122e43SStefano Zampini   PetscScalar     *work,lwork;
108708122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
108808122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
108908122e43SStefano Zampini   PetscReal       *eigs,thresh;
10901b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
1091f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
109208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
109308122e43SStefano Zampini   PetscReal       *rwork;
109408122e43SStefano Zampini #endif
1095b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
1096b1b3d7a2SStefano Zampini 
1097b1b3d7a2SStefano Zampini   PetscFunctionBegin;
1098af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
1099af25d912SStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) 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);
110006a4e24aSStefano Zampini 
1101fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1102fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1103fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1104fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
11051575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1106fd14bc51SStefano Zampini   }
1107fd14bc51SStefano Zampini 
1108e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
1109e496cd5dSStefano 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);
1110e496cd5dSStefano Zampini   }
1111e496cd5dSStefano Zampini 
111208122e43SStefano Zampini   /* max size of subsets */
111308122e43SStefano Zampini   mss = 0;
111408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
111508122e43SStefano Zampini     PetscInt subset_size;
1116862806e4SStefano Zampini 
111708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
111808122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
111908122e43SStefano Zampini   }
112008122e43SStefano Zampini 
112108122e43SStefano Zampini   /* min/max and threshold */
112208122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
1123f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
112408122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
1125f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
1126f6f667cfSStefano Zampini   if (nmin) {
1127f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
1128f6f667cfSStefano Zampini   }
112908122e43SStefano Zampini 
113008122e43SStefano Zampini   /* allocate lapack workspace */
113108122e43SStefano Zampini   cum = cum2 = 0;
113208122e43SStefano Zampini   maxneigs = 0;
113308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
113408122e43SStefano Zampini     PetscInt n,subset_size;
1135f6f667cfSStefano Zampini 
113608122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
113708122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
11389162d606SStefano Zampini     cum += subset_size;
11399162d606SStefano Zampini     cum2 += subset_size*n;
114008122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
114108122e43SStefano Zampini   }
114208122e43SStefano Zampini   if (mss) {
11439ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
114408122e43SStefano Zampini       PetscBLASInt B_itype = 1;
114508122e43SStefano Zampini       PetscBLASInt B_N = mss;
11464c6709b3SStefano Zampini       PetscReal    zero = 0.0;
11474c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
114808122e43SStefano Zampini 
114908122e43SStefano Zampini       B_lwork = -1;
115008122e43SStefano Zampini       S = NULL;
115108122e43SStefano Zampini       St = NULL;
1152a58a30b4SStefano Zampini       eigs = NULL;
1153a58a30b4SStefano Zampini       eigv = NULL;
1154a58a30b4SStefano Zampini       B_iwork = NULL;
1155a58a30b4SStefano Zampini       B_ifail = NULL;
1156d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1157d1710679SStefano Zampini       rwork = NULL;
1158d1710679SStefano Zampini #endif
11598bec7fa6SStefano Zampini       thresh = 1.0;
116008122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
116108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
116208122e43SStefano 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));
116308122e43SStefano Zampini #else
116408122e43SStefano 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));
116508122e43SStefano Zampini #endif
116608122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
116708122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
116808122e43SStefano Zampini     } else {
116908122e43SStefano Zampini         /* TODO */
117008122e43SStefano Zampini     }
117108122e43SStefano Zampini   } else {
117208122e43SStefano Zampini     lwork = 0;
117308122e43SStefano Zampini   }
117408122e43SStefano Zampini 
117508122e43SStefano Zampini   nv = 0;
1176d62866d3SStefano 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) */
1177d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
117808122e43SStefano Zampini   }
11794c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
1180f6f667cfSStefano Zampini   if (allocated_S_St) {
1181f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
1182f6f667cfSStefano Zampini   }
1183f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
118408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
118508122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
118608122e43SStefano Zampini #endif
11879162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
11889162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
11899162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
119008122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
11919162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
119208122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
119308122e43SStefano Zampini 
119408122e43SStefano Zampini   maxneigs = 0;
119572b8c272SStefano Zampini   cum = cumarray = 0;
11969162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
11979162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
1198d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
119908122e43SStefano Zampini     const PetscInt *idxs;
120008122e43SStefano Zampini 
1201d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
120208122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
120308122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
120408122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
120508122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
12069162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
12079162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
120808122e43SStefano Zampini     }
1209d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
121008122e43SStefano Zampini   }
121108122e43SStefano Zampini 
121208122e43SStefano Zampini   if (mss) { /* multilevel */
121308122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
121408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
121508122e43SStefano Zampini   }
121608122e43SStefano Zampini 
1217ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
121808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
121908122e43SStefano Zampini     const PetscInt *idxs;
12209d54b7f4SStefano Zampini     PetscReal      upper,lower;
1221862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
122208122e43SStefano Zampini     PetscBLASInt   B_N;
1223aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
122408122e43SStefano Zampini 
12259d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
12269d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
12279d54b7f4SStefano Zampini       lower = thresh;
12289d54b7f4SStefano Zampini     } else {
12299d54b7f4SStefano Zampini       upper = 1./thresh;
12309d54b7f4SStefano Zampini       lower = 0.;
12319d54b7f4SStefano Zampini     }
1232862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
1233ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
1234f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
1235f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
12369ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
1237aff50787SStefano Zampini         PetscInt j,k;
1238aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
1239aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1240aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
124108122e43SStefano Zampini         }
124208122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1243aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1244aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1245aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1246aff50787SStefano Zampini           }
124708122e43SStefano Zampini         }
124808122e43SStefano Zampini       } else {
124908122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
125008122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
125108122e43SStefano Zampini       }
12528bec7fa6SStefano Zampini     } else {
1253f6f667cfSStefano Zampini       S = Sarray + cumarray;
1254f6f667cfSStefano Zampini       St = Starray + cumarray;
12558bec7fa6SStefano Zampini     }
1256aff50787SStefano Zampini     /* see if we can save some work */
1257b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
1258aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1259aff50787SStefano Zampini     }
1260aff50787SStefano Zampini 
1261b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
1262aff50787SStefano Zampini       B_neigs = 0;
1263aff50787SStefano Zampini     } else {
12649ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
126508122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1266f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
12674c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
12689552c7c7SStefano Zampini         PetscInt     nmin_s;
1269b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
127008122e43SStefano Zampini 
1271fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
12728bec7fa6SStefano 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]]);
1273fd14bc51SStefano Zampini         }
1274d16cbb6bSStefano Zampini 
1275b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
1276b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
1277b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
1278b7ab4a40SStefano Zampini         }
1279b7ab4a40SStefano Zampini 
128008122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1281b7ab4a40SStefano Zampini         if (compute_range) {
1282d16cbb6bSStefano Zampini 
1283d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
128408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
12859d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
128608122e43SStefano Zampini #else
12879d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
128808122e43SStefano Zampini #endif
1289b7ab4a40SStefano Zampini         } else if (!same_data) {
1290d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1291d16cbb6bSStefano Zampini           B_IL = 1;
1292d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
12939d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
1294d16cbb6bSStefano Zampini #else
12959d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
1296d16cbb6bSStefano Zampini #endif
1297b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
1298b7ab4a40SStefano Zampini           PetscInt k;
1299b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
1300b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
1301b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
1302b7ab4a40SStefano Zampini           nmin = nmax;
1303b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1304b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
1305b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
1306b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
1307b7ab4a40SStefano Zampini           }
1308d16cbb6bSStefano Zampini         }
130908122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
131008122e43SStefano Zampini         if (B_ierr) {
13116c4ed002SBarry Smith           if (B_ierr < 0 ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
13126c4ed002SBarry Smith           else if (B_ierr <= B_N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
13136c4ed002SBarry Smith           else 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);
131408122e43SStefano Zampini         }
131508122e43SStefano Zampini 
131608122e43SStefano Zampini         if (B_neigs > nmax) {
1317fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1318fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1319fd14bc51SStefano Zampini           }
13209d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
132108122e43SStefano Zampini           B_neigs = nmax;
132208122e43SStefano Zampini         }
132308122e43SStefano Zampini 
13249552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
13259552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
132608122e43SStefano Zampini           PetscBLASInt B_neigs2;
132708122e43SStefano Zampini 
13289d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
1329f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
13309d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
13319d54b7f4SStefano Zampini           } else {
13329d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
13339d54b7f4SStefano Zampini             B_IU = nmin_s;
13349d54b7f4SStefano Zampini           }
1335fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1336fd14bc51SStefano 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);
1337fd14bc51SStefano Zampini           }
13389ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
133908122e43SStefano Zampini             PetscInt j;
134008122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
134108122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
134208122e43SStefano Zampini             }
134308122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
134408122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
134508122e43SStefano Zampini             }
134608122e43SStefano Zampini           } else {
134708122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
134808122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
134908122e43SStefano Zampini           }
135008122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
135108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
13529d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&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));
135308122e43SStefano Zampini #else
13549d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&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));
135508122e43SStefano Zampini #endif
135608122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
135708122e43SStefano Zampini           B_neigs += B_neigs2;
135808122e43SStefano Zampini         }
135908122e43SStefano Zampini         if (B_ierr) {
13606c4ed002SBarry Smith           if (B_ierr < 0 ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
13616c4ed002SBarry Smith           else if (B_ierr <= B_N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
13626c4ed002SBarry Smith           else 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);
136308122e43SStefano Zampini         }
1364fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1365ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
136608122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
136708122e43SStefano Zampini             if (eigs[j] == 0.0) {
1368ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
136908122e43SStefano Zampini             } else {
13709d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
1371ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
13729d54b7f4SStefano Zampini               } else {
13739d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
13749d54b7f4SStefano Zampini               }
1375fd14bc51SStefano Zampini             }
137608122e43SStefano Zampini           }
137708122e43SStefano Zampini         }
137808122e43SStefano Zampini       } else {
137908122e43SStefano Zampini           /* TODO */
138008122e43SStefano Zampini       }
1381aff50787SStefano Zampini     }
13826c3e6151SStefano Zampini     /* change the basis back to the original one */
13836c3e6151SStefano Zampini     if (sub_schurs->change) {
138472b8c272SStefano Zampini       Mat change,phi,phit;
13856c3e6151SStefano Zampini 
13866c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
13876c3e6151SStefano Zampini         PetscInt ii;
13886c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
13896c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
13906c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
13916c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
13926c3e6151SStefano Zampini           }
13936c3e6151SStefano Zampini         }
13946c3e6151SStefano Zampini       }
139572b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
13966c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
139772b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
13986c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
13996c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
14006c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
14016c3e6151SStefano Zampini     }
14028bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
14038bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
14049162d606SStefano Zampini     if (B_neigs) {
14059162d606SStefano 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);
1406fd14bc51SStefano Zampini 
1407fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
14089552c7c7SStefano Zampini         PetscInt ii;
14099552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1410ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
14119552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1412ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1413ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1414ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1415ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1416ac47001eSStefano Zampini #else
1417ac47001eSStefano 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);
1418ac47001eSStefano Zampini #endif
14199552c7c7SStefano Zampini           }
14209552c7c7SStefano Zampini         }
1421fd14bc51SStefano Zampini       }
14229162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
14239162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
14249162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
14259162d606SStefano Zampini       cum++;
142608122e43SStefano Zampini     }
142708122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
142808122e43SStefano Zampini     /* shift for next computation */
142908122e43SStefano Zampini     cumarray += subset_size*subset_size;
143008122e43SStefano Zampini   }
1431fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1432fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1433fd14bc51SStefano Zampini   }
143408122e43SStefano Zampini 
143508122e43SStefano Zampini   if (mss) {
143608122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
143708122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1438f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1439f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1440f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
144108122e43SStefano Zampini   }
1442f6f667cfSStefano Zampini   if (allocated_S_St) {
1443f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1444f6f667cfSStefano Zampini   }
1445f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
144608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
144708122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
144808122e43SStefano Zampini #endif
144908122e43SStefano Zampini   if (pcbddc->dbg_flag) {
14501b968477SStefano Zampini     PetscInt maxneigs_r;
1451b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
14529b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
145308122e43SStefano Zampini   }
145408122e43SStefano Zampini   PetscFunctionReturn(0);
145508122e43SStefano Zampini }
1456b1b3d7a2SStefano Zampini 
1457674ae819SStefano Zampini #undef __FUNCT__
1458c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1459c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1460c8587f34SStefano Zampini {
1461c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
14628629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1463c8587f34SStefano Zampini   PetscErrorCode ierr;
1464c8587f34SStefano Zampini 
1465c8587f34SStefano Zampini   PetscFunctionBegin;
1466f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
14675e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1468c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1469c8587f34SStefano Zampini 
1470684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
14710fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1472684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1473c8587f34SStefano Zampini 
1474c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1475b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
1476c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1477c8587f34SStefano Zampini   }
1478c8587f34SStefano Zampini 
14798629588bSStefano Zampini   /*
14808629588bSStefano Zampini      Setup local correction and local part of coarse basis.
14818629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
14828629588bSStefano Zampini   */
148347f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
14848629588bSStefano Zampini 
14858629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
14868629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
14878629588bSStefano Zampini 
14888629588bSStefano Zampini   /* free */
14898629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1490c8587f34SStefano Zampini   PetscFunctionReturn(0);
1491c8587f34SStefano Zampini }
1492c8587f34SStefano Zampini 
1493c8587f34SStefano Zampini #undef __FUNCT__
1494674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1495674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1496674ae819SStefano Zampini {
1497674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1498674ae819SStefano Zampini   PetscErrorCode ierr;
1499674ae819SStefano Zampini 
1500674ae819SStefano Zampini   PetscFunctionBegin;
1501674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1502674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
150330368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1504674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
1505674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1506785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1507674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1508f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1509f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1510785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
151163602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
151263602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1513674ae819SStefano Zampini   PetscFunctionReturn(0);
1514674ae819SStefano Zampini }
1515674ae819SStefano Zampini 
1516674ae819SStefano Zampini #undef __FUNCT__
1517674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1518674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1519674ae819SStefano Zampini {
1520674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15214f1b2e48SStefano Zampini   PetscInt       i;
1522674ae819SStefano Zampini   PetscErrorCode ierr;
1523674ae819SStefano Zampini 
1524674ae819SStefano Zampini   PetscFunctionBegin;
1525b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1526674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
152716909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
15281dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
1529674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1530674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
15314f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
15324f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
15334f1b2e48SStefano Zampini   }
15344f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1535b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1536674ae819SStefano Zampini   PetscFunctionReturn(0);
1537674ae819SStefano Zampini }
1538674ae819SStefano Zampini 
1539674ae819SStefano Zampini #undef __FUNCT__
1540674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1541674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1542674ae819SStefano Zampini {
1543674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1544674ae819SStefano Zampini   PetscErrorCode ierr;
1545674ae819SStefano Zampini 
1546674ae819SStefano Zampini   PetscFunctionBegin;
1547674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
154858da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1549ca92afb2SStefano Zampini     PetscScalar *array;
155006656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
155106656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
155258da7f69SStefano Zampini   }
1553674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1554674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
155515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
155615aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1557674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1558674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1559674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
156006656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1561674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1562674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
15638ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1564674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1565674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1566674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1567f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1568f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1569f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1570f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1571727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
15720e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1573f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
157470cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
157581d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
15760369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
15771dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
15784f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
15798b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1580ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1581ca92afb2SStefano Zampini     PetscInt i;
1582ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1583ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1584ca92afb2SStefano Zampini     }
1585ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1586ca92afb2SStefano Zampini   }
15874f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1588674ae819SStefano Zampini   PetscFunctionReturn(0);
1589674ae819SStefano Zampini }
1590674ae819SStefano Zampini 
1591674ae819SStefano Zampini #undef __FUNCT__
1592f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1593f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
15946bfb1811SStefano Zampini {
15956bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15966bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
15976bfb1811SStefano Zampini   VecType        impVecType;
15984f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
15996bfb1811SStefano Zampini   PetscErrorCode ierr;
16006bfb1811SStefano Zampini 
16016bfb1811SStefano Zampini   PetscFunctionBegin;
16026c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1603e7b262bdSStefano Zampini   /* get sizes */
16044f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1605b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
16066bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1607e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1608e7b262bdSStefano Zampini   /* R nodes */
1609e7b262bdSStefano Zampini   old_size = -1;
1610e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1611e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1612e7b262bdSStefano Zampini   }
1613e7b262bdSStefano Zampini   if (n_R != old_size) {
1614e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1615e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
16166bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
16176bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
16186bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
16196bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1620e7b262bdSStefano Zampini   }
1621e7b262bdSStefano Zampini   /* local primal dofs */
1622e7b262bdSStefano Zampini   old_size = -1;
1623e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1624e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1625e7b262bdSStefano Zampini   }
1626e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1627e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
162883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1629e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
16306bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1631e7b262bdSStefano Zampini   }
1632e7b262bdSStefano Zampini   /* local explicit constraints */
1633e7b262bdSStefano Zampini   old_size = -1;
1634e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1635e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1636e7b262bdSStefano Zampini   }
1637e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1638e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
163983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
164083b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
164183b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
164283b7ccabSStefano Zampini   }
16436bfb1811SStefano Zampini   PetscFunctionReturn(0);
16446bfb1811SStefano Zampini }
16456bfb1811SStefano Zampini 
16466bfb1811SStefano Zampini #undef __FUNCT__
164747f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
164847f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
164988ebb749SStefano Zampini {
165025084f0cSStefano Zampini   PetscErrorCode  ierr;
165125084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
165288ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
165388ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1654d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
165525084f0cSStefano Zampini   /* submatrices of local problem */
165680677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
165706656605SStefano Zampini   /* submatrices of local coarse problem */
165806656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
165925084f0cSStefano Zampini   /* working matrices */
166006656605SStefano Zampini   Mat             C_CR;
166125084f0cSStefano Zampini   /* additional working stuff */
166206656605SStefano Zampini   PC              pc_R;
16634f1b2e48SStefano Zampini   Mat             F;
16645cbda25cSStefano Zampini   Vec             dummy_vec;
1665a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
166625084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
166706656605SStefano Zampini   PetscScalar     *work;
166806656605SStefano Zampini   PetscInt        *idx_V_B;
1669ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
167006656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1671ffd830a3SStefano Zampini 
167225084f0cSStefano Zampini   /* some shortcuts to scalars */
167306656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
167488ebb749SStefano Zampini 
167588ebb749SStefano Zampini   PetscFunctionBegin;
1676ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1677ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1678ffd830a3SStefano Zampini   }
1679ffd830a3SStefano Zampini 
1680ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1681b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
16824f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1683b371cd4fSStefano Zampini   n_B = pcis->n_B;
1684b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
168588ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
168688ebb749SStefano Zampini 
168788ebb749SStefano Zampini   /* vertices in boundary numbering */
1688785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
16890e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
16906c4ed002SBarry Smith   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D\n",n_vertices,i);
169188ebb749SStefano Zampini 
169206656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1693019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
169406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
169506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
169606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
169706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
169806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
169906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
170006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
170106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
170206656605SStefano Zampini 
170306656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
170406656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
170506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
170606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
170706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1708ffd830a3SStefano Zampini   lda_rhs = n_R;
1709a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
171006656605SStefano Zampini   if (isLU || isILU || isCHOL) {
171106656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1712df4d28bfSStefano Zampini   } else if (sub_schurs->reuse_solver) {
1713df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1714d62866d3SStefano Zampini     MatFactorType      type;
1715d62866d3SStefano Zampini 
1716df4d28bfSStefano Zampini     F = reuse_solver->F;
17176816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1718d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1719ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
172022db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
172106656605SStefano Zampini   } else {
172206656605SStefano Zampini     F = NULL;
172306656605SStefano Zampini   }
172406656605SStefano Zampini 
1725ffd830a3SStefano Zampini   /* allocate workspace */
1726ffd830a3SStefano Zampini   n = 0;
1727ffd830a3SStefano Zampini   if (n_constraints) {
1728ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1729ffd830a3SStefano Zampini   }
1730ffd830a3SStefano Zampini   if (n_vertices) {
1731ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1732ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1733ffd830a3SStefano Zampini   }
1734ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1735ffd830a3SStefano Zampini 
17365cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
17375cbda25cSStefano Zampini   dummy_vec = NULL;
17385cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
17395cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
17405cbda25cSStefano Zampini   }
17415cbda25cSStefano Zampini 
174288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
174388ebb749SStefano Zampini   if (n_constraints) {
174472b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
174506656605SStefano Zampini     IS          is_aux;
174680677318SStefano Zampini     PetscScalar *array,*array2;
174706656605SStefano Zampini 
1748f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
174980677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
175088ebb749SStefano Zampini 
175125084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
175225084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
17538ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
175472b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
175588ebb749SStefano Zampini 
175680677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
175780677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1758ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
175988ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
176006656605SStefano Zampini       const PetscScalar *row_cmat_values;
176106656605SStefano Zampini       const PetscInt    *row_cmat_indices;
176206656605SStefano Zampini       PetscInt          size_of_constraint,j;
176388ebb749SStefano Zampini 
176406656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
176506656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1766ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
176706656605SStefano Zampini       }
176806656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
176906656605SStefano Zampini     }
1770ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
177106656605SStefano Zampini     if (F) {
177206656605SStefano Zampini       Mat B;
177306656605SStefano Zampini 
1774ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1775a3df083aSStefano Zampini       if (need_benign_correction) {
1776df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1777a3df083aSStefano Zampini 
177872b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
177972b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1780a3df083aSStefano Zampini       }
178180677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1782a3df083aSStefano Zampini       if (need_benign_correction) {
1783a3df083aSStefano Zampini         PetscScalar        *marr;
1784df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1785a3df083aSStefano Zampini 
1786a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
17875cbda25cSStefano Zampini         if (lda_rhs != n_R) {
17885cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
17895cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
17905cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
17915cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
17925cbda25cSStefano Zampini           }
17935cbda25cSStefano Zampini         } else {
1794a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
1795a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
17965cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
1797a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1798a3df083aSStefano Zampini           }
17995cbda25cSStefano Zampini         }
1800a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1801a3df083aSStefano Zampini       }
180206656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
180306656605SStefano Zampini     } else {
180480677318SStefano Zampini       PetscScalar *marr;
180580677318SStefano Zampini 
180680677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
180706656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1808ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1809ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
181006656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
181106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
181206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
181306656605SStefano Zampini       }
181480677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
181506656605SStefano Zampini     }
181680677318SStefano Zampini     if (!pcbddc->switch_static) {
181780677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
181880677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
181980677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
182080677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1821ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
182280677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
182380677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
182480677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
182580677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
182680677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
182780677318SStefano Zampini       }
182880677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
182980677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
183072b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
183180677318SStefano Zampini     } else {
1832ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1833ffd830a3SStefano Zampini         IS dummy;
1834ffd830a3SStefano Zampini 
1835ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
183672b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1837ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1838ffd830a3SStefano Zampini       } else {
183980677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
184080677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1841ffd830a3SStefano Zampini       }
184225084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
184380677318SStefano Zampini     }
184480677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
184580677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
184680677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
184706656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
184806656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
184980677318SStefano Zampini     if (isCHOL) {
185080677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
185180677318SStefano Zampini     } else {
185225084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
185380677318SStefano Zampini     }
185480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
185506656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
185625084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
185725084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
185825084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
185980677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
186072b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
186172b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
186206656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
186306656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1864f4ddd8eeSStefano Zampini   }
1865fc227af8SStefano Zampini 
1866fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
186788ebb749SStefano Zampini   if (n_vertices) {
186806656605SStefano Zampini     IS is_aux;
18693a50541eSStefano Zampini 
1870df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
18716816873aSStefano Zampini       IS tis;
18726816873aSStefano Zampini 
18736816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
18746816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
18756816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
18766816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
18776816873aSStefano Zampini     } else {
18783a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
18796816873aSStefano Zampini     }
18809577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
18819577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
188204708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
188325084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
188488ebb749SStefano Zampini   }
188588ebb749SStefano Zampini 
188688ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1887f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
188806656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
188906656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
189006656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
189106656605SStefano Zampini     }
1892f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
189306656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
189406656605SStefano Zampini       PetscScalar *marray;
189506656605SStefano Zampini 
189606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
189706656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1898f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1899f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1900f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1901f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1902f4ddd8eeSStefano Zampini     }
1903f4ddd8eeSStefano Zampini   }
190406656605SStefano Zampini 
1905f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
190606656605SStefano Zampini     PetscScalar *marray;
190788ebb749SStefano Zampini 
190806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
19098eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
191006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
191188ebb749SStefano Zampini     }
19123301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
191306656605SStefano Zampini       n *= 2;
191488ebb749SStefano Zampini     }
191506656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
191606656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
191706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
19188eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
191906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
192006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
192188ebb749SStefano Zampini     }
19223301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
192306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
19248eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
192506656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
192606656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
192788ebb749SStefano Zampini       }
192888ebb749SStefano Zampini     } else {
1929c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1930c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
19311b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1932c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1933c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1934c0553b1fSStefano Zampini       }
193588ebb749SStefano Zampini     }
193606656605SStefano Zampini   }
1937019a44ceSStefano Zampini 
193806656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
19394f1b2e48SStefano Zampini   p0_lidx_I = NULL;
19404f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1941d12edf2fSStefano Zampini     const PetscInt *idxs;
1942d12edf2fSStefano Zampini 
1943d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
19444f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
19454f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
19464f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
19474f1b2e48SStefano Zampini     }
1948d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1949d12edf2fSStefano Zampini   }
1950d16cbb6bSStefano Zampini 
195106656605SStefano Zampini   /* vertices */
195206656605SStefano Zampini   if (n_vertices) {
195316f15bc4SStefano Zampini 
1954af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
195504708bb6SStefano Zampini 
195616f15bc4SStefano Zampini     if (n_R) {
195714393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
195806656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
195916f15bc4SStefano Zampini       PetscScalar  *x,*y;
196004708bb6SStefano Zampini       PetscBool    isseqaij;
196106656605SStefano Zampini 
196221eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
196314393ed6SStefano Zampini       if (need_benign_correction) {
196414393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
196514393ed6SStefano Zampini         IS                     is_p0;
196614393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
196714393ed6SStefano Zampini 
196814393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
196914393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
197014393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
1971af25d912SStefano Zampini         if (n != pcbddc->benign_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %d != %d\n",n,pcbddc->benign_n);
197214393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
197314393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
197414393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
197514393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
197614393ed6SStefano Zampini       }
197714393ed6SStefano Zampini 
1978ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
1979af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
1980ffd830a3SStefano Zampini       } else {
1981ca92afb2SStefano Zampini         PetscScalar    *av,*array;
1982ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
1983ca92afb2SStefano Zampini         PetscInt       n;
1984ca92afb2SStefano Zampini         PetscBool      flg_row;
1985ffd830a3SStefano Zampini 
1986ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
1987ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
19889d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
1989ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1990ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
1991ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
1992ca92afb2SStefano Zampini           PetscInt j;
1993ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
1994ffd830a3SStefano Zampini         }
1995ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1996ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1997ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
1998ffd830a3SStefano Zampini       }
1999ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2000a3df083aSStefano Zampini       if (need_benign_correction) {
2001df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2002a3df083aSStefano Zampini         PetscScalar        *marr;
2003a3df083aSStefano Zampini 
2004a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
200514393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
200614393ed6SStefano Zampini 
200714393ed6SStefano Zampini                | 0 0  0 | (V)
200814393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
200914393ed6SStefano Zampini                | 0 0 -1 | (p0)
201014393ed6SStefano Zampini 
201114393ed6SStefano Zampini         */
2012df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
201314393ed6SStefano Zampini           const PetscScalar *vals;
201414393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
201514393ed6SStefano Zampini           PetscInt          n,j,nz;
201614393ed6SStefano Zampini 
2017df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2018df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
201914393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
202014393ed6SStefano Zampini           for (j=0;j<n;j++) {
202114393ed6SStefano Zampini             PetscScalar val = vals[j];
202214393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
202314393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
202414393ed6SStefano Zampini           }
202514393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2026df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
202714393ed6SStefano Zampini         }
202872b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
202972b8c272SStefano Zampini       }
203072b8c272SStefano Zampini       if (F) {
203114393ed6SStefano Zampini         /* need to correct the rhs */
203272b8c272SStefano Zampini         if (need_benign_correction) {
203372b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
203472b8c272SStefano Zampini           PetscScalar        *marr;
203572b8c272SStefano Zampini 
203672b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
20375cbda25cSStefano Zampini           if (lda_rhs != n_R) {
20385cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
20395cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
20405cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
20415cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
20425cbda25cSStefano Zampini             }
20435cbda25cSStefano Zampini           } else {
2044a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2045a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
20465cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2047a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2048a3df083aSStefano Zampini             }
20495cbda25cSStefano Zampini           }
2050a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
2051a3df083aSStefano Zampini         }
205206656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
205314393ed6SStefano Zampini         /* need to correct the solution */
2054a3df083aSStefano Zampini         if (need_benign_correction) {
2055df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2056a3df083aSStefano Zampini           PetscScalar        *marr;
2057a3df083aSStefano Zampini 
2058a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
20595cbda25cSStefano Zampini           if (lda_rhs != n_R) {
20605cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
20615cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
20625cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
20635cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
20645cbda25cSStefano Zampini             }
20655cbda25cSStefano Zampini           } else {
2066a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2067a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
20685cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2069a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2070a3df083aSStefano Zampini             }
20715cbda25cSStefano Zampini           }
2072a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
2073a3df083aSStefano Zampini         }
207406656605SStefano Zampini       } else {
207506656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
207606656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
2077ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
2078ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
207906656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
208006656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
208106656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
208206656605SStefano Zampini         }
208306656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
208406656605SStefano Zampini       }
208580677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2086ffd830a3SStefano Zampini       /* S_VV and S_CV */
208706656605SStefano Zampini       if (n_constraints) {
208806656605SStefano Zampini         Mat B;
208980677318SStefano Zampini 
2090ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
209180677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
2092ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
2093ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
209480677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
209580677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
209680677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
209780677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
209880677318SStefano Zampini         }
2099ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
210080677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
210180677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
2102ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
210380677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
210406656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
2105ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
2106ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
210706656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
210806656605SStefano Zampini       }
210904708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
211004708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
2111511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
211204708bb6SStefano Zampini       }
2113ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
2114ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
2115ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2116ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
2117ffd830a3SStefano Zampini       }
211806656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
211914393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
212014393ed6SStefano Zampini       if (need_benign_correction) {
2121df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
212214393ed6SStefano Zampini         PetscScalar      *marr,*sums;
212314393ed6SStefano Zampini 
212414393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
212514393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
2126df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
212714393ed6SStefano Zampini           const PetscScalar *vals;
212814393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
212914393ed6SStefano Zampini           PetscInt          n,j,nz;
213014393ed6SStefano Zampini 
2131df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2132df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
213314393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
213414393ed6SStefano Zampini             PetscInt k;
213514393ed6SStefano Zampini             sums[j] = 0.;
213614393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
213714393ed6SStefano Zampini           }
213814393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
213914393ed6SStefano Zampini           for (j=0;j<n;j++) {
214014393ed6SStefano Zampini             PetscScalar val = vals[j];
214114393ed6SStefano Zampini             PetscInt k;
214214393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
214314393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
214414393ed6SStefano Zampini             }
214514393ed6SStefano Zampini           }
214614393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2147df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
214814393ed6SStefano Zampini         }
214914393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
215014393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
215114393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
215214393ed6SStefano Zampini       }
215380677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
215406656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
215506656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
215606656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
215706656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
215806656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
215906656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
216006656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2161d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
2162019a44ceSStefano Zampini     } else {
2163d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2164d16cbb6bSStefano Zampini     }
216521eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
2166d16cbb6bSStefano Zampini 
216706656605SStefano Zampini     /* coarse basis functions */
216806656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
216916f15bc4SStefano Zampini       PetscScalar *y;
217016f15bc4SStefano Zampini 
2171ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
217206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
217306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
217406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
217506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
217606656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
217706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
217806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
217906656605SStefano Zampini 
218006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
21814f1b2e48SStefano Zampini         PetscInt j;
21824f1b2e48SStefano Zampini 
218306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
218406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
218506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
21884f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
218906656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
219006656605SStefano Zampini       }
219106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
219206656605SStefano Zampini     }
219304708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
219404708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
219506656605SStefano Zampini   }
21965cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
219706656605SStefano Zampini 
219806656605SStefano Zampini   if (n_constraints) {
219906656605SStefano Zampini     Mat B;
220006656605SStefano Zampini 
2201ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
220206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
220380677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
220406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
220506656605SStefano Zampini     if (n_vertices) {
220680677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
220780677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
220880677318SStefano Zampini       } else {
220980677318SStefano Zampini         Mat S_VCt;
221080677318SStefano Zampini 
2211ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
2212ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
221372b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
2214ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
2215ffd830a3SStefano Zampini         }
221680677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
221780677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
221880677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
221980677318SStefano Zampini       }
222006656605SStefano Zampini     }
222106656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
222206656605SStefano Zampini     /* coarse basis functions */
222306656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
222406656605SStefano Zampini       PetscScalar *y;
222506656605SStefano Zampini 
2226ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
222706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
222806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
222906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
223006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
223106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
223206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
223306656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
22344f1b2e48SStefano Zampini         PetscInt j;
22354f1b2e48SStefano Zampini 
223606656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
223706656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
223806656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
223906656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
224006656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
22414f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
224206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
224306656605SStefano Zampini       }
224406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
224506656605SStefano Zampini     }
224606656605SStefano Zampini   }
224780677318SStefano Zampini   if (n_constraints) {
224880677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
224980677318SStefano Zampini   }
22504f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
225172b8c272SStefano Zampini 
225272b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
225372b8c272SStefano Zampini   if (pcbddc->benign_n) {
225472b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
225572b8c272SStefano Zampini     IS          is_dummy;
225672b8c272SStefano Zampini     PetscScalar *data;
225772b8c272SStefano Zampini     PetscInt    j;
225872b8c272SStefano Zampini 
225972b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
226072b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
226172b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
226272b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
226386c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
226472b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
226572b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
226672b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
226772b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
226872b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
226972b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
227072b8c272SStefano Zampini       }
227172b8c272SStefano Zampini     }
227272b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
227372b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
227472b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
227572b8c272SStefano Zampini   }
2276019a44ceSStefano Zampini 
227706656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
22783301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
2279ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
2280ffd830a3SStefano Zampini     PetscScalar *marray;
228106656605SStefano Zampini 
228206656605SStefano Zampini     if (n_constraints) {
2283ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
228406656605SStefano Zampini 
2285af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
228606656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
2287ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
228816f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
228906656605SStefano Zampini       if (n_vertices) {
2290ffd830a3SStefano Zampini         Mat S_VCT;
229106656605SStefano Zampini 
229206656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
2293ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
229416f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
229506656605SStefano Zampini       }
2296ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
229706656605SStefano Zampini     }
229816f15bc4SStefano Zampini     if (n_vertices && n_R) {
2299ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2300ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2301ffd830a3SStefano Zampini       PetscInt       n;
2302ffd830a3SStefano Zampini       PetscBool      flg_row;
230306656605SStefano Zampini 
2304ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2305af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
2306ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2307ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2308ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2309ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2310ffd830a3SStefano Zampini         PetscInt j;
2311ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2312ffd830a3SStefano Zampini       }
2313ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2314ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2315ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
231606656605SStefano Zampini     }
231706656605SStefano Zampini 
2318ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2319ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2320ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2321ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2322ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
232306656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
232406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
232506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
232606656605SStefano Zampini     }
2327ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2328ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2329ffd830a3SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2330ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2331ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2332ffd830a3SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2333ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2334ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
233506656605SStefano Zampini     }
2336ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
233706656605SStefano Zampini     /* coarse basis functions */
233806656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
233906656605SStefano Zampini       PetscScalar *y;
234006656605SStefano Zampini 
2341ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
234206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
234306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
234406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
234506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
234606656605SStefano Zampini       if (i<n_vertices) {
234706656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
234806656605SStefano Zampini       }
234906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
235006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
235106656605SStefano Zampini 
235206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
235306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
235406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
235506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
235606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
235706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
235806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
235906656605SStefano Zampini       }
236006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
236106656605SStefano Zampini     }
2362ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2363ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
236406656605SStefano Zampini   }
2365d62866d3SStefano Zampini   /* free memory */
236688ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
236706656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
236806656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
236906656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
237006656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2371d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2372d62866d3SStefano Zampini   if (n_vertices) {
2373d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2374d62866d3SStefano Zampini   }
2375d62866d3SStefano Zampini   if (n_constraints) {
2376d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2377d62866d3SStefano Zampini   }
237888ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
237988ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
238088ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2381d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
238288ebb749SStefano Zampini     Mat         coarse_sub_mat;
238325084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
238488ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
238588ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
238688ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
23878bec7fa6SStefano Zampini     Mat         C_B,CPHI;
23888bec7fa6SStefano Zampini     IS          is_dummy;
23898bec7fa6SStefano Zampini     Vec         mones;
239088ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
239188ebb749SStefano Zampini     PetscReal   real_value;
239288ebb749SStefano Zampini 
2393a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2394a3df083aSStefano Zampini       Mat A;
2395a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2396a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2397a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2398a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2399a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2400a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2401a3df083aSStefano Zampini     } else {
240288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
240388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
240488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
240588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2406a3df083aSStefano Zampini     }
240788ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
240888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2409ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
241088ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
241188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
241288ebb749SStefano Zampini     }
241388ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
241488ebb749SStefano Zampini 
241525084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
24163301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
241725084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2418ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
241988ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
242088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
242188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
242288ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
242388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
242488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
242588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
242688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
242788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
242888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
242988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
243088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
243188ebb749SStefano Zampini     } else {
243288ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
243388ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
243488ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
243588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
243688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
243788ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
243888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
243988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
244088ebb749SStefano Zampini     }
244188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
244288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
244388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2444511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
24454f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2446fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
2447d12edf2fSStefano Zampini       PetscScalar *data,*data2;
24484f1b2e48SStefano Zampini       PetscInt    j;
2449d12edf2fSStefano Zampini 
24504f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2451fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
2452d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
245386c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2454d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2455d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
24564f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
24574f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2458d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
24594f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
24604f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
24614f1b2e48SStefano Zampini         }
2462d12edf2fSStefano Zampini       }
2463d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2464d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2465d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2466d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2467d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2468d12edf2fSStefano Zampini     }
2469d12edf2fSStefano Zampini #if 0
2470d12edf2fSStefano Zampini   {
2471d12edf2fSStefano Zampini     PetscViewer viewer;
2472d12edf2fSStefano Zampini     char filename[256];
2473ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2474d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2475d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2476ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2477ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2478ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2479d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
248072b8c272SStefano Zampini     if (save_change) {
248172b8c272SStefano Zampini       Mat phi_B;
248272b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
248372b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
248472b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
248572b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
248672b8c272SStefano Zampini     } else {
2487ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2488ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
248972b8c272SStefano Zampini     }
2490ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2491ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2492ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2493ffd830a3SStefano Zampini     }
2494ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2495ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2496ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2497ffd830a3SStefano Zampini     }
249872b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
2499ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2500ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2501ffd830a3SStefano Zampini     }
2502d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2503d12edf2fSStefano Zampini   }
2504d12edf2fSStefano Zampini #endif
250581d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
25068bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
25071575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
250806656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
25098bec7fa6SStefano Zampini 
25108bec7fa6SStefano Zampini     /* check constraints */
2511a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2512a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
25134f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
25148bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2515a00504b5SStefano Zampini     } else {
2516a00504b5SStefano Zampini       PetscScalar *data;
2517a00504b5SStefano Zampini       Mat         tmat;
2518a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2519a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
2520a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2521a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2522a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2523a00504b5SStefano Zampini     }
25248bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
25258bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
25268bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
25278bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2528bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2529ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
2530bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2531bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2532bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2533bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2534bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
253588ebb749SStefano Zampini     }
25368bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
25378bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
25388bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
25398bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
254025084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
254188ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
254288ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
254388ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
254488ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
254588ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
254688ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
254788ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
254888ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
254988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
255088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2551ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
255288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
255388ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
255488ebb749SStefano Zampini     }
255588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
255688ebb749SStefano Zampini   }
25578629588bSStefano Zampini   /* get back data */
25588629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
255988ebb749SStefano Zampini   PetscFunctionReturn(0);
256088ebb749SStefano Zampini }
256188ebb749SStefano Zampini 
256288ebb749SStefano Zampini #undef __FUNCT__
2563d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2564d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2565aa0d41d4SStefano Zampini {
2566d65f70fdSStefano Zampini   Mat            *work_mat;
2567d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2568d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2569d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
2570aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2571aa0d41d4SStefano Zampini 
2572aa0d41d4SStefano Zampini   PetscFunctionBegin;
2573d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2574d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2575d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2576d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2577aa0d41d4SStefano Zampini 
2578d65f70fdSStefano Zampini   if (!rsorted) {
2579906d46d4SStefano Zampini     const PetscInt *idxs;
2580906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2581aa0d41d4SStefano Zampini 
2582d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2583d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2584d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2585d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2586aa0d41d4SStefano Zampini     }
2587d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2588d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2589d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2590d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2591aa0d41d4SStefano Zampini     }
2592d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2593d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2594d65f70fdSStefano Zampini   } else {
2595d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2596d65f70fdSStefano Zampini     isrow_s = isrow;
2597aa0d41d4SStefano Zampini   }
2598906d46d4SStefano Zampini 
2599d65f70fdSStefano Zampini   if (!csorted) {
2600d65f70fdSStefano Zampini     if (isrow == iscol) {
2601d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2602d65f70fdSStefano Zampini       iscol_s = isrow_s;
2603d65f70fdSStefano Zampini     } else {
2604d65f70fdSStefano Zampini       const PetscInt *idxs;
2605d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
2606906d46d4SStefano Zampini 
2607d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2608d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2609d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2610d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2611d65f70fdSStefano Zampini       }
2612d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2613d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2614d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2615d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2616d65f70fdSStefano Zampini       }
2617d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2618d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2619d65f70fdSStefano Zampini     }
2620d65f70fdSStefano Zampini   } else {
2621d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2622d65f70fdSStefano Zampini     iscol_s = iscol;
2623d65f70fdSStefano Zampini   }
2624d65f70fdSStefano Zampini 
2625d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2626d65f70fdSStefano Zampini 
2627d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2628906d46d4SStefano Zampini     Mat      new_mat;
2629d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2630906d46d4SStefano Zampini 
2631d65f70fdSStefano Zampini     if (!rsorted) {
2632d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2633d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2634d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2635d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2636906d46d4SStefano Zampini       }
2637d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2638d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2639d65f70fdSStefano Zampini     } else {
2640d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2641906d46d4SStefano Zampini     }
2642d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2643d65f70fdSStefano Zampini 
2644d65f70fdSStefano Zampini     if (!csorted) {
2645d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2646d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2647d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2648d65f70fdSStefano Zampini       } else {
2649d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2650d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2651d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2652d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2653d65f70fdSStefano Zampini         }
2654d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2655d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2656d65f70fdSStefano Zampini       }
2657d65f70fdSStefano Zampini     } else {
2658d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2659d65f70fdSStefano Zampini     }
2660d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2661d65f70fdSStefano Zampini 
2662d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2663d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2664d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2665d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2666d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2667d65f70fdSStefano Zampini   }
2668d65f70fdSStefano Zampini 
2669d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2670d65f70fdSStefano Zampini   *B = work_mat[0];
2671d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2672d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2673d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2674d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2675d65f70fdSStefano Zampini }
2676d65f70fdSStefano Zampini 
2677d65f70fdSStefano Zampini #undef __FUNCT__
26785e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
26795e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2680aa0d41d4SStefano Zampini {
2681aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
26825e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2683d65f70fdSStefano Zampini   Mat            new_mat;
26845e8657edSStefano Zampini   IS             is_local,is_global;
2685d65f70fdSStefano Zampini   PetscInt       local_size;
2686d65f70fdSStefano Zampini   PetscBool      isseqaij;
2687aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2688aa0d41d4SStefano Zampini 
2689aa0d41d4SStefano Zampini   PetscFunctionBegin;
2690aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
26915e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
26925e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2693b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2694aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2695d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2696aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2697906d46d4SStefano Zampini 
2698906d46d4SStefano Zampini   /* check */
2699906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2700906d46d4SStefano Zampini     Vec       x,x_change;
2701906d46d4SStefano Zampini     PetscReal error;
2702906d46d4SStefano Zampini 
27035e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2704906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
27055e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2706e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2707e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2708d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2709e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2710e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2711906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2712906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2713906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2714906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2715906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2716906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2717906d46d4SStefano Zampini   }
2718906d46d4SStefano Zampini 
271922d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
27209b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
272122d5777bSStefano Zampini   if (isseqaij) {
2722a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2723a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2724aa0d41d4SStefano Zampini   } else {
2725a00504b5SStefano Zampini     Mat work_mat;
27261cf9b237SStefano Zampini 
2727a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2728aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2729a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2730aa0d41d4SStefano Zampini   }
27313301b35fSStefano Zampini   if (matis->A->symmetric_set) {
27323301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2733e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
27343301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2735e496cd5dSStefano Zampini #endif
27363301b35fSStefano Zampini   }
2737d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2738aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2739aa0d41d4SStefano Zampini }
2740aa0d41d4SStefano Zampini 
2741aa0d41d4SStefano Zampini #undef __FUNCT__
2742a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
27438ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2744a64d13efSStefano Zampini {
2745a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2746a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2747d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
274853892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
27493a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
27503a50541eSStefano Zampini   PetscInt        vbs,bs;
27516816873aSStefano Zampini   PetscBT         bitmask=NULL;
2752a64d13efSStefano Zampini   PetscErrorCode  ierr;
2753a64d13efSStefano Zampini 
2754a64d13efSStefano Zampini   PetscFunctionBegin;
2755b23d619eSStefano Zampini   /*
2756b23d619eSStefano Zampini     No need to setup local scatters if
2757b23d619eSStefano Zampini       - primal space is unchanged
2758b23d619eSStefano Zampini         AND
2759b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2760b23d619eSStefano Zampini         AND
2761b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2762b23d619eSStefano Zampini   */
2763b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2764f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2765f4ddd8eeSStefano Zampini   }
2766f4ddd8eeSStefano Zampini   /* destroy old objects */
2767f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2768f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2769f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2770a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2771b371cd4fSStefano Zampini   n_B = pcis->n_B;
2772b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2773b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
27743a50541eSStefano Zampini 
2775a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
27766816873aSStefano Zampini 
277753892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2778df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
2779854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2780a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2781a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
27820e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2783a64d13efSStefano Zampini     }
2784a64d13efSStefano Zampini 
2785a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
27864641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
27876816873aSStefano Zampini         idx_R_local[n_R++] = i;
2788a64d13efSStefano Zampini       }
2789a64d13efSStefano Zampini     }
2790df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2791df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
27926816873aSStefano Zampini 
2793df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2794df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
27956816873aSStefano Zampini   }
27963a50541eSStefano Zampini 
27973a50541eSStefano Zampini   /* Block code */
27983a50541eSStefano Zampini   vbs = 1;
27993a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
28003a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
28013a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
28023a50541eSStefano Zampini     PetscInt  *vary;
2803df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
2804785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
28053a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2806d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2807d3df7717SStefano 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 */
28080e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2809d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
28103a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
28113a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
28123a50541eSStefano Zampini           break;
28133a50541eSStefano Zampini         }
28143a50541eSStefano Zampini       }
2815d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2816d3df7717SStefano Zampini     } else {
2817d3df7717SStefano Zampini       /* Verify directly the R set */
2818d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2819d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2820d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2821d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2822d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2823d3df7717SStefano Zampini             break;
2824d3df7717SStefano Zampini           }
2825d3df7717SStefano Zampini         }
2826d3df7717SStefano Zampini       }
2827d3df7717SStefano Zampini     }
28283a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
28293a50541eSStefano Zampini       vbs = bs;
28303a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
28313a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
28323a50541eSStefano Zampini       }
28333a50541eSStefano Zampini     }
28343a50541eSStefano Zampini   }
28353a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2836df4d28bfSStefano Zampini   if (sub_schurs->reuse_solver) {
2837df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
283853892102SStefano Zampini 
2839df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2840df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
284153892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2842df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
284353892102SStefano Zampini   } else {
28443a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
284553892102SStefano Zampini   }
2846a64d13efSStefano Zampini 
2847a64d13efSStefano Zampini   /* print some info if requested */
2848a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2849a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2850a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
28511575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2852a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2853a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
28544f1b2e48SStefano 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);
2855a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2856a64d13efSStefano Zampini   }
2857a64d13efSStefano Zampini 
2858a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
2859df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
28606816873aSStefano Zampini     IS       is_aux1,is_aux2;
28616816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
28626816873aSStefano Zampini 
28633a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2864854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2865854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2866a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
28674641a718SStefano Zampini     for (i=0; i<n_D; i++) {
28684641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
28694641a718SStefano Zampini     }
2870a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2871a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
28724641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
28734641a718SStefano Zampini         aux_array1[j++] = i;
2874a64d13efSStefano Zampini       }
2875a64d13efSStefano Zampini     }
2876a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2877a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2878a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
28794641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
28804641a718SStefano Zampini         aux_array2[j++] = i;
2881a64d13efSStefano Zampini       }
2882a64d13efSStefano Zampini     }
2883a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2884a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2885a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2886a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2887a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2888a64d13efSStefano Zampini 
28898eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2890785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2891a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
28924641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
28934641a718SStefano Zampini           aux_array1[j++] = i;
2894a64d13efSStefano Zampini         }
2895a64d13efSStefano Zampini       }
2896a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2897a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2898a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2899a64d13efSStefano Zampini     }
29004641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
29013a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2902d62866d3SStefano Zampini   } else {
2903df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
29046816873aSStefano Zampini     IS                 tis;
29056816873aSStefano Zampini     PetscInt           schur_size;
29066816873aSStefano Zampini 
2907df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
29086816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
2909df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
29106816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
29116816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
29126816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
29136816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
29146816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2915d62866d3SStefano Zampini     }
2916d62866d3SStefano Zampini   }
2917a64d13efSStefano Zampini   PetscFunctionReturn(0);
2918a64d13efSStefano Zampini }
2919a64d13efSStefano Zampini 
2920304d26faSStefano Zampini 
2921304d26faSStefano Zampini #undef __FUNCT__
2922304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2923684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2924304d26faSStefano Zampini {
2925304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2926304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2927304d26faSStefano Zampini   PC             pc_temp;
2928304d26faSStefano Zampini   Mat            A_RR;
2929f4ddd8eeSStefano Zampini   MatReuse       reuse;
2930304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2931304d26faSStefano Zampini   PetscReal      value;
293204708bb6SStefano Zampini   PetscInt       n_D,n_R;
29339577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
2934304d26faSStefano Zampini   PetscErrorCode ierr;
2935e604994aSStefano Zampini   /* prefixes stuff */
2936312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2937e604994aSStefano Zampini   size_t         len;
2938304d26faSStefano Zampini 
2939304d26faSStefano Zampini   PetscFunctionBegin;
2940304d26faSStefano Zampini 
2941e604994aSStefano Zampini   /* compute prefixes */
2942e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2943e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2944e604994aSStefano Zampini   if (!pcbddc->current_level) {
2945e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2946e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2947e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2948e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2949e604994aSStefano Zampini   } else {
2950e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2951312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2952e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2953e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2954312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2955312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
295634d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
295734d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2958e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2959e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2960e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
2961e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
2962e604994aSStefano Zampini   }
2963e604994aSStefano Zampini 
2964304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
2965684f6988SStefano Zampini   if (dirichlet) {
2966d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2967450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2968450f8f5eSStefano Zampini       if (!sub_schurs->reuse_solver) {
2969450f8f5eSStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
2970450f8f5eSStefano Zampini       }
2971450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
2972a3df083aSStefano Zampini         Mat    A_IIn;
2973a3df083aSStefano Zampini 
2974a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
2975a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
2976a3df083aSStefano Zampini         pcis->A_II = A_IIn;
2977a3df083aSStefano Zampini       }
2978450f8f5eSStefano Zampini     }
29793301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
29803301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2981964fefecSStefano Zampini     }
2982ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
2983964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
2984304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
2985304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
2986304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
2987304d26faSStefano Zampini       /* default */
2988304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
2989e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
29909577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2991304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
29929577ea80SStefano Zampini       if (issbaij) {
29939577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
29949577ea80SStefano Zampini       } else {
2995304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
29969577ea80SStefano Zampini       }
2997304d26faSStefano Zampini       /* Allow user's customization */
2998304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
2999304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3000304d26faSStefano Zampini     }
3001d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
3002df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
3003df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3004d62866d3SStefano Zampini 
3005df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
3006d5574798SStefano Zampini     }
3007304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3008304d26faSStefano Zampini     if (!n_D) {
3009304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
3010304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3011304d26faSStefano Zampini     }
3012304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
3013304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
3014304d26faSStefano Zampini     /* set ksp_D into pcis data */
3015304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
3016304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
3017304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
3018684f6988SStefano Zampini   }
3019304d26faSStefano Zampini 
3020304d26faSStefano Zampini   /* NEUMANN PROBLEM */
3021684f6988SStefano Zampini   A_RR = 0;
3022684f6988SStefano Zampini   if (neumann) {
3023d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
302404708bb6SStefano Zampini     PetscInt        ibs,mbs;
302504708bb6SStefano Zampini     PetscBool       issbaij;
302604708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
3027f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
30288ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
3029f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
3030f4ddd8eeSStefano Zampini       PetscInt nn_R;
303181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
3032f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3033f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
3034f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
3035f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
3036f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3037f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3038f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
3039727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
3040f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3041f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
3042f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
3043f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
3044f4ddd8eeSStefano Zampini         }
3045f4ddd8eeSStefano Zampini       }
3046f4ddd8eeSStefano Zampini       /* last check */
3047d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
3048f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3049f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3050f4ddd8eeSStefano Zampini       }
3051f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
3052f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
3053f4ddd8eeSStefano Zampini     }
3054a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
3055af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3056af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
305704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
305804708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
305904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
306004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
306104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
3062af732b37SStefano Zampini       } else {
3063511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
30646816873aSStefano Zampini       }
306504708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
306604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
306704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
306804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
306904708bb6SStefano Zampini       } else {
3070511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
307104708bb6SStefano Zampini       }
307204708bb6SStefano Zampini     }
3073a00504b5SStefano Zampini     /* extract A_RR */
3074a00504b5SStefano Zampini     if (sub_schurs->reuse_solver) {
3075a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3076a00504b5SStefano Zampini 
3077a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
307816e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3079a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
308016e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
308116e386b8SStefano Zampini         } else {
3082a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
3083a00504b5SStefano Zampini         }
3084a00504b5SStefano Zampini       } else {
3085a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3086a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
3087a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3088a00504b5SStefano Zampini       }
3089a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
3090f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
309116e386b8SStefano Zampini     }
30923301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
30933301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
30946816873aSStefano Zampini     }
3095f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
3096304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
3097304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
3098304d26faSStefano Zampini       /* default */
3099304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3100e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
3101304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
31029577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
31039577ea80SStefano Zampini       if (issbaij) {
31049577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
31059577ea80SStefano Zampini       } else {
3106304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
31079577ea80SStefano Zampini       }
3108304d26faSStefano Zampini       /* Allow user's customization */
3109304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3110304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3111304d26faSStefano Zampini     }
3112304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3113304d26faSStefano Zampini     if (!n_R) {
3114304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
3115304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3116304d26faSStefano Zampini     }
31175cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
3118df4d28bfSStefano Zampini     /* Reuse solver if it is present */
3119df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
3120df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3121d62866d3SStefano Zampini 
3122df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
3123d62866d3SStefano Zampini     }
3124304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
3125304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
3126684f6988SStefano Zampini   }
3127304d26faSStefano Zampini 
3128304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
31290fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
3130684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
3131684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
31321575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3133684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3134684f6988SStefano Zampini     }
3135684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
31360fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
31370fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
31380fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
31390fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
31400fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
3141304d26faSStefano Zampini       /* need to be adapted? */
3142b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
3143b2566f29SBarry Smith       ierr = MPIU_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3144b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
3145304d26faSStefano Zampini       /* print info */
3146304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
3147e604994aSStefano 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);
3148304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3149304d26faSStefano Zampini       }
3150b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
3151298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
3152304d26faSStefano Zampini       }
3153684f6988SStefano Zampini     }
3154684f6988SStefano Zampini     if (neumann) { /* Neumann */
31550fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
31560fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
31570fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
31580fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
31590fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
3160304d26faSStefano Zampini       /* need to be adapted? */
3161b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
3162b2566f29SBarry Smith       ierr = MPIU_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3163304d26faSStefano Zampini       /* print info */
3164304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
3165e604994aSStefano 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);
3166304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3167304d26faSStefano Zampini       }
3168b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
3169298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
3170304d26faSStefano Zampini       }
31710fccc4e9SStefano Zampini     }
3172684f6988SStefano Zampini   }
31735cbda25cSStefano Zampini   /* free Neumann problem's matrix */
31745cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3175304d26faSStefano Zampini   PetscFunctionReturn(0);
3176304d26faSStefano Zampini }
3177304d26faSStefano Zampini 
3178304d26faSStefano Zampini #undef __FUNCT__
3179ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
318080677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
3181674ae819SStefano Zampini {
3182674ae819SStefano Zampini   PetscErrorCode  ierr;
3183674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3184be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3185674ae819SStefano Zampini 
3186674ae819SStefano Zampini   PetscFunctionBegin;
3187df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
318880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
318920c7b377SStefano Zampini   }
319080677318SStefano Zampini   if (!pcbddc->switch_static) {
319180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
319280677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
319380677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
319420c7b377SStefano Zampini     }
3195df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
319680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
319780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
319820c7b377SStefano Zampini     } else {
3199df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3200be83ff47SStefano Zampini 
3201df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3202df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
320320c7b377SStefano Zampini     }
3204be83ff47SStefano Zampini   } else {
320580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
320680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
320780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
320880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
320980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
321080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
321180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
321280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
321380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3214674ae819SStefano Zampini     }
3215674ae819SStefano Zampini   }
321672b8c272SStefano Zampini   if (!sub_schurs->reuse_solver || pcbddc->switch_static) {
321780677318SStefano Zampini     if (applytranspose) {
321880677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
321980677318SStefano Zampini     } else {
322080677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
322180677318SStefano Zampini     }
3222be83ff47SStefano Zampini   } else {
3223df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3224be83ff47SStefano Zampini 
3225be83ff47SStefano Zampini     if (applytranspose) {
3226df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3227be83ff47SStefano Zampini     } else {
3228df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3229be83ff47SStefano Zampini     }
3230be83ff47SStefano Zampini   }
323180677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
323280677318SStefano Zampini   if (!pcbddc->switch_static) {
3233df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
323480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
323580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3236be83ff47SStefano Zampini     } else {
3237df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3238be83ff47SStefano Zampini 
3239df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3240df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3241be83ff47SStefano Zampini     }
324280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
324380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
324480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
324580677318SStefano Zampini     }
324680677318SStefano Zampini   } else {
324780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
324880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
324980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
325080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
325180677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
325280677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
325380677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
325480677318SStefano Zampini     }
325580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
325680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
325780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
325880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3259674ae819SStefano Zampini   }
3260674ae819SStefano Zampini   PetscFunctionReturn(0);
3261674ae819SStefano Zampini }
3262674ae819SStefano Zampini 
3263dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
3264674ae819SStefano Zampini #undef __FUNCT__
3265674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
3266dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
3267674ae819SStefano Zampini {
3268674ae819SStefano Zampini   PetscErrorCode ierr;
3269674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3270674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
3271674ae819SStefano Zampini   const PetscScalar zero = 0.0;
3272674ae819SStefano Zampini 
3273674ae819SStefano Zampini   PetscFunctionBegin;
3274dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
32754fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3276dc359a40SStefano Zampini     if (applytranspose) {
3277674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
32788eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3279dc359a40SStefano Zampini     } else {
3280674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3281674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
328215aaf578SStefano Zampini     }
32834fee134fSStefano Zampini   } else {
32844fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
32854fee134fSStefano Zampini   }
3286efc2fbd9SStefano Zampini 
3287efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
32884f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
3289efc2fbd9SStefano Zampini     PetscScalar *array;
32904f1b2e48SStefano Zampini     PetscInt    j;
3291efc2fbd9SStefano Zampini 
3292efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
32934f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
3294efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3295efc2fbd9SStefano Zampini   }
3296efc2fbd9SStefano Zampini 
329712edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
329812edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
329912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
330012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
330112edc857SStefano Zampini 
33029f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
330312edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
330412edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
330551694757SStefano Zampini     Mat          coarse_mat;
3306964fefecSStefano Zampini     Vec          rhs,sol;
330751694757SStefano Zampini     MatNullSpace nullsp;
330827b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
3309964fefecSStefano Zampini 
331027b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
331127b6a85dSStefano Zampini       PC        coarse_pc;
331227b6a85dSStefano Zampini 
331327b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
331427b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
331527b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
331627b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
331727b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
331827b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
33193bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
332027b6a85dSStefano Zampini       }
332127b6a85dSStefano Zampini     }
3322964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3323964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
332451694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
332551694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
332651694757SStefano Zampini     if (nullsp) {
332751694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
332851694757SStefano Zampini     }
332912edc857SStefano Zampini     if (applytranspose) {
3330*1f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only) {
3331*1f4df5f7SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
33322701bc32SStefano Zampini       } else {
3333964fefecSStefano Zampini         ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
33342701bc32SStefano Zampini       }
33352701bc32SStefano Zampini     } else {
3336*1f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
33372701bc32SStefano Zampini         PC        coarse_pc;
33382701bc32SStefano Zampini 
33392701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
33402701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
33412701bc32SStefano Zampini         ierr = PCApply(coarse_pc,rhs,sol);CHKERRQ(ierr);
33422701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
334312edc857SStefano Zampini       } else {
3344964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
334512edc857SStefano Zampini       }
33462701bc32SStefano Zampini     }
334727b6a85dSStefano Zampini     /* we don't the benign correction at coarser levels anymore */
334827b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
334927b6a85dSStefano Zampini       PC        coarse_pc;
335027b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
335127b6a85dSStefano Zampini 
335227b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
335327b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
335427b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
33553bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
335627b6a85dSStefano Zampini     }
335751694757SStefano Zampini     if (nullsp) {
335851694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
335951694757SStefano Zampini     }
336012edc857SStefano Zampini   }
3361674ae819SStefano Zampini 
3362674ae819SStefano Zampini   /* Local solution on R nodes */
33634fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
336480677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
33659f00e9b4SStefano Zampini   }
33669f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
33679f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
336812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3369674ae819SStefano Zampini 
33704fee134fSStefano Zampini   /* Sum contributions from the two levels */
33714fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3372dc359a40SStefano Zampini     if (applytranspose) {
3373dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3374dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3375dc359a40SStefano Zampini     } else {
3376674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
33778eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3378dc359a40SStefano Zampini     }
3379efc2fbd9SStefano Zampini     /* store p0 */
33804f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3381efc2fbd9SStefano Zampini       PetscScalar *array;
33824f1b2e48SStefano Zampini       PetscInt    j;
3383efc2fbd9SStefano Zampini 
3384efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
33854f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3386efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3387efc2fbd9SStefano Zampini     }
33884fee134fSStefano Zampini   } else { /* expand the coarse solution */
33894fee134fSStefano Zampini     if (applytranspose) {
33904fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
33914fee134fSStefano Zampini     } else {
33924fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
33934fee134fSStefano Zampini     }
33944fee134fSStefano Zampini   }
3395674ae819SStefano Zampini   PetscFunctionReturn(0);
3396674ae819SStefano Zampini }
3397674ae819SStefano Zampini 
3398674ae819SStefano Zampini #undef __FUNCT__
3399674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
340012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3401674ae819SStefano Zampini {
3402674ae819SStefano Zampini   PetscErrorCode ierr;
3403674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
340458da7f69SStefano Zampini   PetscScalar    *array;
340512edc857SStefano Zampini   Vec            from,to;
3406674ae819SStefano Zampini 
3407674ae819SStefano Zampini   PetscFunctionBegin;
340812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
340912edc857SStefano Zampini     from = pcbddc->coarse_vec;
341012edc857SStefano Zampini     to = pcbddc->vec1_P;
341112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
341212edc857SStefano Zampini       Vec tvec;
341358da7f69SStefano Zampini 
341458da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
341558da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
341612edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
341758da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
341858da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
341958da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
342012edc857SStefano Zampini     }
342112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
342212edc857SStefano Zampini     from = pcbddc->vec1_P;
342312edc857SStefano Zampini     to = pcbddc->coarse_vec;
342412edc857SStefano Zampini   }
342512edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3426674ae819SStefano Zampini   PetscFunctionReturn(0);
3427674ae819SStefano Zampini }
3428674ae819SStefano Zampini 
3429674ae819SStefano Zampini #undef __FUNCT__
3430674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
343112edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3432674ae819SStefano Zampini {
3433674ae819SStefano Zampini   PetscErrorCode ierr;
3434674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
343558da7f69SStefano Zampini   PetscScalar    *array;
343612edc857SStefano Zampini   Vec            from,to;
3437674ae819SStefano Zampini 
3438674ae819SStefano Zampini   PetscFunctionBegin;
343912edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
344012edc857SStefano Zampini     from = pcbddc->coarse_vec;
344112edc857SStefano Zampini     to = pcbddc->vec1_P;
344212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
344312edc857SStefano Zampini     from = pcbddc->vec1_P;
344412edc857SStefano Zampini     to = pcbddc->coarse_vec;
344512edc857SStefano Zampini   }
344612edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
344712edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
344812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
344912edc857SStefano Zampini       Vec tvec;
345058da7f69SStefano Zampini 
345112edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
345258da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
345358da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
345458da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
345558da7f69SStefano Zampini     }
345658da7f69SStefano Zampini   } else {
345758da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
345858da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
345912edc857SStefano Zampini     }
346012edc857SStefano Zampini   }
3461674ae819SStefano Zampini   PetscFunctionReturn(0);
3462674ae819SStefano Zampini }
3463674ae819SStefano Zampini 
3464984c4197SStefano Zampini /* uncomment for testing purposes */
3465984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3466674ae819SStefano Zampini #undef __FUNCT__
3467674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3468674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3469674ae819SStefano Zampini {
3470674ae819SStefano Zampini   PetscErrorCode    ierr;
3471674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3472674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3473674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3474984c4197SStefano Zampini   /* one and zero */
3475984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3476984c4197SStefano Zampini   /* space to store constraints and their local indices */
34779162d606SStefano Zampini   PetscScalar       *constraints_data;
34789162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
34799162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
34809162d606SStefano Zampini   PetscInt          *constraints_n;
3481984c4197SStefano Zampini   /* iterators */
3482b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3483984c4197SStefano Zampini   /* BLAS integers */
3484e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3485e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3486c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3487727cdba6SStefano Zampini   /* reuse */
34880e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
34890e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3490984c4197SStefano Zampini   /* change of basis */
3491b3d85658SStefano Zampini   PetscBool         qr_needed;
34929162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3493984c4197SStefano Zampini   /* auxiliary stuff */
349464efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
34958a0068c3SStefano Zampini   PetscInt          ncc;
3496984c4197SStefano Zampini   /* some quantities */
349745a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3498a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3499984c4197SStefano Zampini 
3500674ae819SStefano Zampini   PetscFunctionBegin;
35018e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
35028e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
35038e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
350416909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
3505088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3506088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
35070e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
35080e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
35090e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
35100e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
35110e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3512088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3513cf5a6209SStefano Zampini 
3514cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
35159162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3516cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3517cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3518cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3519cf5a6209SStefano Zampini     PetscScalar  *array;
3520cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3521cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3522674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3523b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3524674ae819SStefano Zampini     PetscScalar  *work;
3525674ae819SStefano Zampini     PetscReal    *singular_vals;
3526674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3527674ae819SStefano Zampini     PetscReal    *rwork;
3528674ae819SStefano Zampini #endif
3529674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3530674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3531674ae819SStefano Zampini #else
3532964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3533964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3534674ae819SStefano Zampini #endif
3535674ae819SStefano Zampini 
3536674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3537d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3538e4d548c7SStefano Zampini     /* print some info */
3539*1f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
3540e4d548c7SStefano Zampini       PetscInt nv;
3541e4d548c7SStefano Zampini 
3542e4d548c7SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
3543e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
3544e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3545e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3546e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3547e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
3548e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
3549e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3550e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3551e4d548c7SStefano Zampini     }
3552e4d548c7SStefano Zampini 
3553d06fc5fdSStefano Zampini     /* free unneeded index sets */
3554d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3555d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3556674ae819SStefano Zampini     }
3557d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3558d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3559d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3560d06fc5fdSStefano Zampini       }
3561d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3562d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3563d06fc5fdSStefano Zampini     }
3564d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3565d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3566d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3567d06fc5fdSStefano Zampini       }
3568d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3569d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3570d06fc5fdSStefano Zampini     }
357170022509SStefano Zampini 
357270022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
357370022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
357470022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
357570022509SStefano Zampini     if (pcbddc->NullSpace) {
357670022509SStefano Zampini       PetscBool tbool[2],gbool[2];
357770022509SStefano Zampini 
357870022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
3579b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
3580d06fc5fdSStefano Zampini         if (!ISForEdges) {
3581d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
3582d06fc5fdSStefano Zampini         }
3583b8ffe317SStefano Zampini       }
3584d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
3585d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
3586b2566f29SBarry Smith       ierr = MPIU_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3587d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
3588d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
358998a51de6SStefano Zampini     }
359070022509SStefano Zampini #endif
359108122e43SStefano Zampini 
3592674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3593674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3594674ae819SStefano Zampini     if (nearnullsp) {
3595674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3596f4ddd8eeSStefano Zampini       /* remove any stored info */
3597f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3598f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3599f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3600f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3601f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3602473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3603f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3604f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3605f4ddd8eeSStefano Zampini       }
3606984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3607984c4197SStefano Zampini       nnsp_size = 0;
3608674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3609674ae819SStefano Zampini     }
3610984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3611984c4197SStefano Zampini     max_constraints = nnsp_size;
3612984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3613984c4197SStefano Zampini 
3614674ae819SStefano Zampini     /*
3615674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
36169162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
36179162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
36189162d606SStefano Zampini          There can be multiple constraints per connected component
3619674ae819SStefano Zampini                                                                                                                                                            */
3620674ae819SStefano Zampini     n_vertices = 0;
3621674ae819SStefano Zampini     if (ISForVertices) {
3622674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3623674ae819SStefano Zampini     }
36249162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
36259162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
36269162d606SStefano Zampini 
36279162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
36289162d606SStefano Zampini     total_counts *= max_constraints;
3629674ae819SStefano Zampini     total_counts += n_vertices;
36304641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
36319162d606SStefano Zampini 
3632674ae819SStefano Zampini     total_counts = 0;
3633674ae819SStefano Zampini     max_size_of_constraint = 0;
3634674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
36359162d606SStefano Zampini       IS used_is;
3636674ae819SStefano Zampini       if (i<n_ISForEdges) {
36379162d606SStefano Zampini         used_is = ISForEdges[i];
3638674ae819SStefano Zampini       } else {
36399162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3640674ae819SStefano Zampini       }
36419162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3642674ae819SStefano Zampini       total_counts += j;
3643674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3644674ae819SStefano Zampini     }
36459162d606SStefano 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);
36469162d606SStefano Zampini 
3647984c4197SStefano Zampini     /* get local part of global near null space vectors */
3648785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3649984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3650984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3651e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3652e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3653984c4197SStefano Zampini     }
3654674ae819SStefano Zampini 
3655242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3656242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3657a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3658242a89d7SStefano Zampini 
3659984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3660a773dcb8SStefano Zampini     if (!skip_lapack) {
3661674ae819SStefano Zampini       PetscScalar temp_work;
3662911cabfeSStefano Zampini 
3663674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3664984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3665785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3666785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3667785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3668674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3669785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3670674ae819SStefano Zampini #endif
3671674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3672c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3673c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3674674ae819SStefano Zampini       lwork = -1;
3675674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3676674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3677c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3678674ae819SStefano Zampini #else
3679c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3680674ae819SStefano Zampini #endif
3681674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3682984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3683674ae819SStefano Zampini #else /* on missing GESVD */
3684674ae819SStefano Zampini       /* SVD */
3685674ae819SStefano Zampini       PetscInt max_n,min_n;
3686674ae819SStefano Zampini       max_n = max_size_of_constraint;
3687984c4197SStefano Zampini       min_n = max_constraints;
3688984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3689674ae819SStefano Zampini         min_n = max_size_of_constraint;
3690984c4197SStefano Zampini         max_n = max_constraints;
3691674ae819SStefano Zampini       }
3692785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3693674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3694785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3695674ae819SStefano Zampini #endif
3696674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3697674ae819SStefano Zampini       lwork = -1;
3698e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3699e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3700b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3701674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3702674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
37039162d606SStefano 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));
3704674ae819SStefano Zampini #else
37059162d606SStefano 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));
3706674ae819SStefano Zampini #endif
3707674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3708984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3709984c4197SStefano Zampini #endif /* on missing GESVD */
3710674ae819SStefano Zampini       /* Allocate optimal workspace */
3711674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3712854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3713674ae819SStefano Zampini     }
3714674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3715674ae819SStefano Zampini     total_counts = 0;
37169162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
37179162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3718674ae819SStefano Zampini     /* vertices */
37199162d606SStefano Zampini     if (n_vertices) {
3720674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
37219162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3722674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
37239162d606SStefano Zampini         constraints_n[total_counts] = 1;
37249162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
37259162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
37269162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3727674ae819SStefano Zampini         total_counts++;
3728674ae819SStefano Zampini       }
3729674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3730674ae819SStefano Zampini       n_vertices = total_counts;
3731674ae819SStefano Zampini     }
3732984c4197SStefano Zampini 
3733674ae819SStefano Zampini     /* edges and faces */
37349162d606SStefano Zampini     total_counts_cc = total_counts;
3735911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
37369162d606SStefano Zampini       IS        used_is;
37379162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
37389162d606SStefano Zampini 
3739911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
37409162d606SStefano Zampini         used_is = ISForEdges[ncc];
3741984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3742674ae819SStefano Zampini       } else {
37439162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3744984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3745674ae819SStefano Zampini       }
3746674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
37479162d606SStefano Zampini 
37489162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
37499162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3750984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3751984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3752674ae819SStefano Zampini       if (nnsp_has_cnst) {
37535b08dc53SStefano Zampini         PetscScalar quad_value;
37549162d606SStefano Zampini 
37559162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
37569162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
37579162d606SStefano Zampini 
3758a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3759674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3760a773dcb8SStefano Zampini         } else {
3761a773dcb8SStefano Zampini           quad_value = 1.0;
3762a773dcb8SStefano Zampini         }
3763674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
37649162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3765674ae819SStefano Zampini         }
37669162d606SStefano Zampini         temp_constraints++;
3767674ae819SStefano Zampini         total_counts++;
3768674ae819SStefano Zampini       }
3769674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3770984c4197SStefano Zampini         PetscReal real_value;
37719162d606SStefano Zampini         PetscScalar *ptr_to_data;
37729162d606SStefano Zampini 
3773984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
37749162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3775674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
37769162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3777674ae819SStefano Zampini         }
3778984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3779984c4197SStefano Zampini         /* check if array is null on the connected component */
3780e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
37819162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
37825b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3783674ae819SStefano Zampini           temp_constraints++;
3784674ae819SStefano Zampini           total_counts++;
37859162d606SStefano Zampini           if (!idxs_copied) {
37869162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
37879162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3788674ae819SStefano Zampini           }
3789674ae819SStefano Zampini         }
37909162d606SStefano Zampini       }
37919162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
379245a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3793eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3794a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
37959162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
37969162d606SStefano Zampini 
37979162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3798a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
37999162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3800a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
38019162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3802a773dcb8SStefano Zampini         } else { /* perform SVD */
3803984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
38049162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3805674ae819SStefano Zampini 
3806674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3807984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3808984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3809984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3810984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3811984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3812984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3813984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3814984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3815674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3816e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3817984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3818674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3819674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
38209162d606SStefano 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));
3821674ae819SStefano Zampini             }
3822674ae819SStefano Zampini           }
3823e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3824e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3825e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3826674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3827c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3828674ae819SStefano Zampini #else
3829c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3830674ae819SStefano Zampini #endif
3831674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3832984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3833984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3834674ae819SStefano Zampini           j = 0;
3835984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3836674ae819SStefano Zampini           total_counts = total_counts-j;
383745a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3838e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3839c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3840c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3841c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3842c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3843c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3844c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3845674ae819SStefano Zampini           if (j<temp_constraints) {
3846984c4197SStefano Zampini             PetscInt ii;
3847984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3848674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38499162d606SStefano 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));
3850674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3851984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3852674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
38539162d606SStefano 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];
3854674ae819SStefano Zampini               }
3855674ae819SStefano Zampini             }
3856674ae819SStefano Zampini           }
3857674ae819SStefano Zampini #else  /* on missing GESVD */
3858e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3859e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3860b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3861674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3862674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
38639162d606SStefano 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));
3864674ae819SStefano Zampini #else
38659162d606SStefano 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));
3866674ae819SStefano Zampini #endif
3867984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3868674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3869984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3870e310c8b4SStefano Zampini           k = temp_constraints;
3871e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3872674ae819SStefano Zampini           j = 0;
3873e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
387445a1bb75SStefano Zampini           valid_constraints = k-j;
3875911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3876984c4197SStefano Zampini #endif /* on missing GESVD */
3877674ae819SStefano Zampini         }
3878a773dcb8SStefano Zampini       }
38799162d606SStefano Zampini       /* update pointers information */
38809162d606SStefano Zampini       if (valid_constraints) {
38819162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
38829162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
38839162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
38849162d606SStefano Zampini         /* set change_of_basis flag */
388545a1bb75SStefano Zampini         if (boolforchange) {
3886b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
38879162d606SStefano Zampini         }
3888b3d85658SStefano Zampini         total_counts_cc++;
388945a1bb75SStefano Zampini       }
389045a1bb75SStefano Zampini     }
3891984c4197SStefano Zampini     /* free workspace */
38928f1c130eSStefano Zampini     if (!skip_lapack) {
3893984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3894984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3895984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3896984c4197SStefano Zampini #endif
3897984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3898984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3899984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3900984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3901984c4197SStefano Zampini #endif
3902984c4197SStefano Zampini     }
3903984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3904984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3905984c4197SStefano Zampini     }
3906984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3907cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3908cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3909cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3910cf5a6209SStefano Zampini     }
3911cf5a6209SStefano Zampini     if (n_ISForFaces) {
3912cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3913cf5a6209SStefano Zampini     }
3914cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3915cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3916cf5a6209SStefano Zampini     }
3917cf5a6209SStefano Zampini     if (n_ISForEdges) {
3918cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3919cf5a6209SStefano Zampini     }
3920cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
392108122e43SStefano Zampini   } else {
392208122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3923984c4197SStefano Zampini 
392408122e43SStefano Zampini     total_counts = 0;
392508122e43SStefano Zampini     n_vertices = 0;
3926d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3927d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
392808122e43SStefano Zampini     }
392908122e43SStefano Zampini     max_constraints = 0;
39309162d606SStefano Zampini     total_counts_cc = 0;
393108122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
393208122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
39339162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
393408122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
393508122e43SStefano Zampini     }
39369162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
39379162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
39389162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
39399162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
394074d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
39419162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
39429162d606SStefano Zampini     total_counts_cc = 0;
39439162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
39449162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
39459162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
394608122e43SStefano Zampini       }
394708122e43SStefano Zampini     }
39489162d606SStefano Zampini #if 0
39499162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
39509162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
39519162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
39529162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
39539162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
39549162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
39559162d606SStefano Zampini       }
39569162d606SStefano Zampini       printf("\n");
39579162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
39589162d606SStefano Zampini     }
39591b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
39608bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
39611b968477SStefano Zampini     }
39621b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
39638bec7fa6SStefano 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]);
39641b968477SStefano Zampini     }
396508122e43SStefano Zampini #endif
396608122e43SStefano Zampini 
39678bec7fa6SStefano Zampini     max_size_of_constraint = 0;
39689162d606SStefano 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]);
39699162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
397008122e43SStefano Zampini     /* Change of basis */
3971b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
397208122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
397308122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
397408122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3975b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
397608122e43SStefano Zampini         }
397708122e43SStefano Zampini       }
397808122e43SStefano Zampini     }
397908122e43SStefano Zampini   }
3980984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
39814f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
398208122e43SStefano Zampini 
39839162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
39849162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
39856c4ed002SBarry Smith   if (i != constraints_idxs_ptr[total_counts_cc]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %D != %D\n",constraints_idxs_ptr[total_counts_cc],i);
3986674ae819SStefano Zampini 
3987674ae819SStefano Zampini   /* Create constraint matrix */
3988674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
398916f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
3990984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
3991984c4197SStefano Zampini 
3992984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
3993a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
3994a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
399574d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
3996984c4197SStefano Zampini   total_primal_vertices=0;
3997b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
39989162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
39999162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
400072b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
40019162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
4002b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
400364efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
40049162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
40059162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
4006a717540cSStefano Zampini       }
4007b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
400891af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
4009a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
4010a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
4011a717540cSStefano Zampini       }
4012fa434743SStefano Zampini     } else {
4013b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
4014fa434743SStefano Zampini     }
4015a717540cSStefano Zampini   }
4016b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
4017b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
4018674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
401970022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4020b3d85658SStefano Zampini 
40214f1b2e48SStefano 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);
40220e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
40230e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
4024984c4197SStefano Zampini 
4025984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
402674d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
4027785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
4028984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
402974d5cdf7SStefano Zampini 
4030984c4197SStefano Zampini   j = total_primal_vertices;
403174d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
4032b3d85658SStefano Zampini   cum = total_primal_vertices;
40339162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
40344641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
4035b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
4036b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
4037b3d85658SStefano Zampini       cum++;
40389162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
403974d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
404074d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
404174d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
404274d5cdf7SStefano Zampini       }
40439162d606SStefano Zampini       j += constraints_n[i];
4044674ae819SStefano Zampini     }
4045674ae819SStefano Zampini   }
4046674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
4047674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
4048088faed8SStefano Zampini 
4049674ae819SStefano Zampini   /* set values in constraint matrix */
4050984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
40510e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4052674ae819SStefano Zampini   }
4053984c4197SStefano Zampini   total_counts = total_primal_vertices;
40549162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
40554641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
40569162d606SStefano Zampini       PetscInt *cols;
40579162d606SStefano Zampini 
40589162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
40599162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
40609162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
40619162d606SStefano Zampini         PetscInt    row = total_counts+k;
40629162d606SStefano Zampini         PetscScalar *vals;
40639162d606SStefano Zampini 
40649162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
40659162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
40669162d606SStefano Zampini       }
40679162d606SStefano Zampini       total_counts += constraints_n[i];
4068674ae819SStefano Zampini     }
4069674ae819SStefano Zampini   }
4070674ae819SStefano Zampini   /* assembling */
4071674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4072674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4073088faed8SStefano Zampini 
4074984c4197SStefano Zampini   /*
40756a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4076984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
4077f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
4078984c4197SStefano Zampini   */
4079674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
4080674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
4081026de310SStefano Zampini     /* dual and primal dofs on a single cc */
4082984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
4083984c4197SStefano Zampini     /* working stuff for GEQRF */
408481d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
4085984c4197SStefano Zampini     PetscBLASInt lqr_work;
4086984c4197SStefano Zampini     /* working stuff for UNGQR */
4087984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
4088984c4197SStefano Zampini     PetscBLASInt lgqr_work;
4089984c4197SStefano Zampini     /* working stuff for TRTRS */
4090984c4197SStefano Zampini     PetscScalar  *trs_rhs;
40913f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
4092984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
4093984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
4094984c4197SStefano Zampini     PetscScalar  *start_vals;
4095984c4197SStefano Zampini     /* working stuff for values insertion */
40964641a718SStefano Zampini     PetscBT      is_primal;
409764efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
4098906d46d4SStefano Zampini     /* matrix sizes */
4099906d46d4SStefano Zampini     PetscInt     global_size,local_size;
4100906d46d4SStefano Zampini     /* temporary change of basis */
4101906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
4102cf5a6209SStefano Zampini     /* extra space for debugging */
4103cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
4104984c4197SStefano Zampini 
4105906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
4106906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
410716f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
4108bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
4109906d46d4SStefano Zampini     /* nonzeros for local mat */
4110bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
41111dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4112bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
41131dd7afcfSStefano Zampini     } else {
41141dd7afcfSStefano Zampini       const PetscInt *ii;
41151dd7afcfSStefano Zampini       PetscInt       n;
41161dd7afcfSStefano Zampini       PetscBool      flg_row;
41171dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
41181dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
41191dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
41201dd7afcfSStefano Zampini     }
41219162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
4122a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
41239162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
4124a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
41259162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
4126a717540cSStefano Zampini         } else {
41279162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
41289162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
4129a717540cSStefano Zampini         }
4130a717540cSStefano Zampini       }
4131a717540cSStefano Zampini     }
4132906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
4133bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
41341dd7afcfSStefano Zampini     /* Set interior change in the matrix */
41351dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4136bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
4137906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
4138a717540cSStefano Zampini       }
41391dd7afcfSStefano Zampini     } else {
41401dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
41411dd7afcfSStefano Zampini       PetscScalar    *aa;
41421dd7afcfSStefano Zampini       PetscInt       n;
41431dd7afcfSStefano Zampini       PetscBool      flg_row;
41441dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
41451dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
41461dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
41471dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
41481dd7afcfSStefano Zampini       }
41491dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
41501dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
41511dd7afcfSStefano Zampini     }
4152a717540cSStefano Zampini 
4153a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
4154a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4155a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4156a717540cSStefano Zampini     }
4157a717540cSStefano Zampini 
4158a717540cSStefano Zampini 
4159a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
4160a717540cSStefano Zampini     /*
4161a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
4162a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
4163a717540cSStefano Zampini 
4164a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
4165a717540cSStefano Zampini 
4166a6b551f4SStefano 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)
4167a6b551f4SStefano Zampini 
4168a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
4169a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
4170a717540cSStefano Zampini             |              ...                        |
4171a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
4172a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
4173a717540cSStefano Zampini 
4174a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
4175a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
4176a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
4177a6b551f4SStefano Zampini 
4178a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
4179a717540cSStefano Zampini     */
4180a717540cSStefano Zampini     if (qr_needed) {
4181984c4197SStefano Zampini       /* space to store Q */
4182854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
4183984c4197SStefano Zampini       /* first we issue queries for optimal work */
41843f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
41853f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
41863f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4187984c4197SStefano Zampini       lqr_work = -1;
41883f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
4189984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
4190984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
4191785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
4192984c4197SStefano Zampini       lgqr_work = -1;
41933f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
41943f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
41953f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
41963f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
41973f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
41983f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
4199984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
4200984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
4201785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
4202984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
4203785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
4204984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
4205785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
4206a717540cSStefano Zampini       /* allocating workspace for check */
4207a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
4208cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
4209a717540cSStefano Zampini       }
4210a717540cSStefano Zampini     }
4211984c4197SStefano Zampini     /* array to store whether a node is primal or not */
42124641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
4213473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
42140e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
42156c4ed002SBarry Smith     if (i != total_primal_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %D != %D\n",total_primal_vertices,i);
421639e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
421739e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
421839e2fb2aSStefano Zampini     }
421939e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
4220984c4197SStefano Zampini 
4221a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
42229162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
42239162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
42244641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
4225984c4197SStefano Zampini         /* get constraint info */
42269162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
4227984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
4228984c4197SStefano Zampini 
4229984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
42309162d606SStefano 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);
4231674ae819SStefano Zampini         }
4232984c4197SStefano Zampini 
4233fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
4234a717540cSStefano Zampini 
4235a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
4236a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
42379162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4238a717540cSStefano Zampini           }
4239984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
42409162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4241984c4197SStefano Zampini 
4242984c4197SStefano Zampini           /* compute QR decomposition of constraints */
42433f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42443f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42453f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4246674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42473f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
4248984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
4249674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4250984c4197SStefano Zampini 
4251984c4197SStefano Zampini           /* explictly compute R^-T */
4252984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
4253984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
42543f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42553f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
42563f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
42573f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
4258984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42593f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
4260984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
4261984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4262984c4197SStefano Zampini 
4263a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
42643f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42653f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
42663f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
42673f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4268984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42693f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
4270984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
4271984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4272984c4197SStefano Zampini 
4273984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
4274984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
4275984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
42763f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42773f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42783f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
42793f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
42803f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
42813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4282984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42839162d606SStefano 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));
4284984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
42859162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4286984c4197SStefano Zampini 
4287984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
42889162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
4289984c4197SStefano Zampini           /* insert cols for primal dofs */
4290984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
4291984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
42929162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4293906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4294984c4197SStefano Zampini           }
4295984c4197SStefano Zampini           /* insert cols for dual dofs */
4296984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
42979162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
4298984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
42999162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4300906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4301984c4197SStefano Zampini               j++;
4302674ae819SStefano Zampini             }
4303674ae819SStefano Zampini           }
4304984c4197SStefano Zampini 
4305984c4197SStefano Zampini           /* check change of basis */
4306984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
4307984c4197SStefano Zampini             PetscInt   ii,jj;
4308984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
4309c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
4310c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4311c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
4312c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4313c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
4314c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
4315984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4316cf5a6209SStefano 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));
4317984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4318984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
4319984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
4320cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
4321cf5a6209SStefano 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;
4322674ae819SStefano Zampini               }
4323674ae819SStefano Zampini             }
4324984c4197SStefano Zampini             if (!valid_qr) {
432522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
4326984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
4327984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
4328cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
4329cf5a6209SStefano 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]));
4330674ae819SStefano Zampini                   }
4331cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
4332cf5a6209SStefano 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]));
4333984c4197SStefano Zampini                   }
4334984c4197SStefano Zampini                 }
4335984c4197SStefano Zampini               }
4336674ae819SStefano Zampini             } else {
433722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
4338674ae819SStefano Zampini             }
4339674ae819SStefano Zampini           }
4340a717540cSStefano Zampini         } else { /* simple transformation block */
4341a717540cSStefano Zampini           PetscInt    row,col;
4342a6b551f4SStefano Zampini           PetscScalar val,norm;
4343a6b551f4SStefano Zampini 
4344a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
43459162d606SStefano 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));
4346a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
43479162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
43489162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4349bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
43509162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
4351906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
43529162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
4353a717540cSStefano Zampini             } else {
4354a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
43559162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4356a717540cSStefano Zampini                 if (row != col) {
43579162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
4358a717540cSStefano Zampini                 } else {
43599162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
4360a717540cSStefano Zampini                 }
4361906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
4362a717540cSStefano Zampini               }
4363a717540cSStefano Zampini             }
4364a717540cSStefano Zampini           }
436598a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
436622d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4367a717540cSStefano Zampini           }
4368674ae819SStefano Zampini         }
4369984c4197SStefano Zampini       } else {
4370984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
43719162d606SStefano 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);
4372674ae819SStefano Zampini         }
4373674ae819SStefano Zampini       }
4374674ae819SStefano Zampini     }
4375a717540cSStefano Zampini 
4376a717540cSStefano Zampini     /* free workspace */
4377a717540cSStefano Zampini     if (qr_needed) {
4378984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4379cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4380984c4197SStefano Zampini       }
4381984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4382984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4383984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4384984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4385984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4386674ae819SStefano Zampini     }
4387a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4388906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4389906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4390906d46d4SStefano Zampini 
4391906d46d4SStefano Zampini     /* assembling of global change of variable */
439288c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
4393bbb9e6c6SStefano Zampini       Mat      tmat;
439416f15bc4SStefano Zampini       PetscInt bs;
439516f15bc4SStefano Zampini 
4396906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4397906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4398bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4399bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4400bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4401bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
440216f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
440316f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4404906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4405bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4406bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4407bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4408bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4409bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4410e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4411e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4412bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4413bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
441488c03ad3SStefano Zampini 
4415906d46d4SStefano Zampini       /* check */
4416906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
4417906d46d4SStefano Zampini         PetscReal error;
4418906d46d4SStefano Zampini         Vec       x,x_change;
4419906d46d4SStefano Zampini 
4420906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4421906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4422906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4423906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4424e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4425e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4426bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4427e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4428e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4429906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4430906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4431906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4432906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4433bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4434906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
4435906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4436906d46d4SStefano Zampini       }
4437b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
4438b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
4439b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4440bf3a8328SStefano Zampini 
4441bf3a8328SStefano Zampini         if (pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined) {
4442bf3a8328SStefano Zampini           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints");CHKERRQ(ierr);
4443bf3a8328SStefano Zampini         }
4444b96c3477SStefano Zampini         if (sub_schurs->S_Ej_all) {
4445ac632422SStefano Zampini           Mat                    S_new,tmat;
4446bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
4447bbb9e6c6SStefano Zampini 
4448bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
44496816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4450bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4451bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
4452bf3a8328SStefano Zampini             IS                     is_V;
4453b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4454b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4455b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4456b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4457b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4458bf3a8328SStefano Zampini           }
4459bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4460ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4461b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4462ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4463bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4464bf3a8328SStefano Zampini             const PetscScalar *array;
4465bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
4466bf3a8328SStefano Zampini             PetscInt          i,n_V;
4467bf3a8328SStefano Zampini 
4468b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4469b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4470b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4471b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4472b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4473b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
4474b087196eSStefano Zampini               PetscScalar val;
4475b087196eSStefano Zampini               PetscInt    idx;
4476b087196eSStefano Zampini 
4477b087196eSStefano Zampini               idx = idxs_V[i];
4478b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
4479b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4480b087196eSStefano Zampini             }
4481b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4482b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4483bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4484bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4485bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4486bf3a8328SStefano Zampini           }
4487ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
4488ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4489ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
4490ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4491b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4492ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4493bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
4494b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4495bf3a8328SStefano Zampini             }
4496ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
4497ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4498ac632422SStefano Zampini           }
4499b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
450088c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4501b96c3477SStefano Zampini         }
4502c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
4503c9db6a07SStefano Zampini         if (sub_schurs->change) {
4504c9db6a07SStefano Zampini           PetscInt i;
4505c9db6a07SStefano Zampini 
4506c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
4507c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
4508c9db6a07SStefano Zampini           }
4509c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
4510c9db6a07SStefano Zampini         }
4511b96c3477SStefano Zampini       }
451216909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
451316909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
451416909a7fSStefano Zampini       } else {
4515906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
451616909a7fSStefano Zampini       }
45171dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
451827b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
451972b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
452072b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
452172b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
452272b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
452372b8c272SStefano Zampini     }
45241dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
452527b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
4526b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4527b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4528906d46d4SStefano Zampini     } else {
45291dd7afcfSStefano Zampini       Mat benign_global = NULL;
453027b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
45311dd7afcfSStefano Zampini         Mat tmat;
45321dd7afcfSStefano Zampini 
45331dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
45341dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
45351dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
45361dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
45371dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
45381dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
45391dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
45401dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
45411dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
45421dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
45431dd7afcfSStefano Zampini           Mat M;
45441dd7afcfSStefano Zampini 
45451dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
45461dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
45471dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
45481dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
4549906d46d4SStefano Zampini         } else {
45501dd7afcfSStefano Zampini           Mat         eye;
45511dd7afcfSStefano Zampini           PetscScalar *array;
45521dd7afcfSStefano Zampini 
45531dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
45541dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
45551dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
45561dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
4557906d46d4SStefano Zampini           }
45581dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
45591dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45601dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45611dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
45621dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
45631dd7afcfSStefano Zampini         }
45641dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
45651dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
45661dd7afcfSStefano Zampini       }
45671dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
45681dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
45691dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
457027b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
45711dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
45721dd7afcfSStefano Zampini       }
45731dd7afcfSStefano Zampini     }
457416909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
457516909a7fSStefano Zampini       IS             is_global;
457616909a7fSStefano Zampini       const PetscInt *gidxs;
457716909a7fSStefano Zampini 
457816909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
457916909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
458016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
458116909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
458216909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
458316909a7fSStefano Zampini     }
45841dd7afcfSStefano Zampini   }
45851dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
45861dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
4587b9b85e73SStefano Zampini   }
4588a717540cSStefano Zampini 
458972b8c272SStefano Zampini   if (!pcbddc->fake_change) {
45904f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
45914f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
45924f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
45934f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4594019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4595019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
4596019a44ceSStefano Zampini       pcbddc->local_primal_size++;
4597019a44ceSStefano Zampini     }
4598019a44ceSStefano Zampini 
4599019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
4600727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
4601727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
46029f47a83aSStefano 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);
4603c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
46040e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
46059f47a83aSStefano 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);
4606727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4607727cdba6SStefano Zampini       }
46080e6343abSStefano Zampini     }
4609727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4610b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
461172b8c272SStefano Zampini   }
461272b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4613727cdba6SStefano Zampini 
4614a717540cSStefano Zampini   /* flush dbg viewer */
4615b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4616b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4617b8ffe317SStefano Zampini   }
4618a717540cSStefano Zampini 
4619e310c8b4SStefano Zampini   /* free workspace */
4620a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
46214641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
462208122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
46239162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
46249162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
462508122e43SStefano Zampini   } else {
46269162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
46279162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
46289162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
462908122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
463008122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
46319162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
46329162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
463308122e43SStefano Zampini   }
4634674ae819SStefano Zampini   PetscFunctionReturn(0);
4635674ae819SStefano Zampini }
4636674ae819SStefano Zampini 
4637674ae819SStefano Zampini #undef __FUNCT__
4638674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4639674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4640674ae819SStefano Zampini {
4641674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4642674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4643674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
464414f95afaSStefano Zampini   PetscInt    ierr,i,N;
4645674ae819SStefano Zampini 
4646674ae819SStefano Zampini   PetscFunctionBegin;
46478e61c736SStefano Zampini   /* Reset previously computed graph */
46488e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4649674ae819SStefano Zampini   /* Init local Graph struct */
46507fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
46513bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4652674ae819SStefano Zampini 
4653575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
46545099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
46555099eff2SStefano 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);
4656575ad6abSStefano Zampini   }
46579577ea80SStefano Zampini 
4658674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4659d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
46604d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
46614d379d7bSStefano Zampini     PetscInt  nvtxs;
4662e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4663674ae819SStefano Zampini 
46642fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
46652fffb893SStefano Zampini     if (flg_row) {
46664d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4667b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
46682fffb893SStefano Zampini     }
46692fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4670674ae819SStefano Zampini   }
46719b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
46729b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4673674ae819SStefano Zampini   }
4674674ae819SStefano Zampini 
4675674ae819SStefano Zampini   /* Setup of Graph */
467614f95afaSStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,pcbddc->vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
4677674ae819SStefano Zampini 
46784f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
46794f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
46804f1b2e48SStefano Zampini     PetscInt *local_subs;
46814f1b2e48SStefano Zampini 
46824f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
46834f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
46844f1b2e48SStefano Zampini       const PetscInt *idxs;
46854f1b2e48SStefano Zampini       PetscInt       nl,j;
46864f1b2e48SStefano Zampini 
46874f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
46884f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
46894f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
46904f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
46914f1b2e48SStefano Zampini       }
46924f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
46934f1b2e48SStefano Zampini     }
46944f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
46954f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
46964f1b2e48SStefano Zampini   }
46974f1b2e48SStefano Zampini 
4698674ae819SStefano Zampini   /* Graph's connected components analysis */
4699674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4700674ae819SStefano Zampini   PetscFunctionReturn(0);
4701674ae819SStefano Zampini }
4702674ae819SStefano Zampini 
4703dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4704674ae819SStefano Zampini #undef __FUNCT__
4705674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4706dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4707674ae819SStefano Zampini {
4708dc456d91SStefano Zampini   PetscSF        sf;
4709dc456d91SStefano Zampini   PetscLayout    map;
4710dc456d91SStefano Zampini   const PetscInt *idxs;
4711dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4712dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4713dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4714dc456d91SStefano Zampini   PetscMPIInt    commsize;
4715674ae819SStefano Zampini   PetscBool      first_found;
4716674ae819SStefano Zampini   PetscErrorCode ierr;
4717674ae819SStefano Zampini 
4718674ae819SStefano Zampini   PetscFunctionBegin;
4719dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4720dc456d91SStefano Zampini   if (subset_mult) {
4721dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4722dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4723dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4724674ae819SStefano Zampini   }
4725dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4726dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4727dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4728dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4729dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4730dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4731674ae819SStefano Zampini   }
4732dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4733b2566f29SBarry Smith   ierr = MPIU_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4734dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4735dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4736dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4737dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4738dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4739dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4740dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4741dc456d91SStefano Zampini 
4742dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4743dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4744dc456d91SStefano Zampini   if (subset_mult) {
4745dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4746dc456d91SStefano Zampini 
4747dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4748dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4749dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4750674ae819SStefano Zampini   } else {
4751dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4752674ae819SStefano Zampini   }
4753dc456d91SStefano Zampini   /* local size of new subset */
4754dc456d91SStefano Zampini   n_n = 0;
4755dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4756dc456d91SStefano Zampini 
4757dc456d91SStefano Zampini   /* global indexes in layout */
4758dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4759dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4760dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4761dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4762dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4763dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4764dc456d91SStefano Zampini 
4765dc456d91SStefano Zampini   /* reduce from leaves to roots */
4766dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
476764a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
476864a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4769dc456d91SStefano Zampini 
4770dc456d91SStefano Zampini   /* count indexes in local part of layout */
4771674ae819SStefano Zampini   nlocals = 0;
4772674ae819SStefano Zampini   first_index = -1;
4773674ae819SStefano Zampini   first_found = PETSC_FALSE;
4774dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4775dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4776674ae819SStefano Zampini       first_found = PETSC_TRUE;
4777674ae819SStefano Zampini       first_index = i;
4778674ae819SStefano Zampini     }
4779dc456d91SStefano Zampini     nlocals += root_data[i];
4780674ae819SStefano Zampini   }
4781dc456d91SStefano Zampini 
4782dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
47835fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4784dc456d91SStefano Zampini   start = 0;
478564a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
47865fa240b1SStefano Zampini #else
478764a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
47885fa240b1SStefano Zampini   start = start-nlocals;
47895fa240b1SStefano Zampini #endif
47905fa240b1SStefano Zampini 
4791dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4792dc456d91SStefano Zampini     *N_n = start + nlocals;
4793dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4794dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4795674ae819SStefano Zampini   }
47965fa240b1SStefano Zampini 
47975fa240b1SStefano Zampini   /* adapt root data with cumulative */
4798674ae819SStefano Zampini   if (first_found) {
4799dc456d91SStefano Zampini     PetscInt old_index;
4800dc456d91SStefano Zampini 
4801dc456d91SStefano Zampini     root_data[first_index] += start;
4802674ae819SStefano Zampini     old_index = first_index;
4803dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4804dc456d91SStefano Zampini       if (root_data[i]) {
4805dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4806674ae819SStefano Zampini         old_index = i;
4807674ae819SStefano Zampini       }
4808674ae819SStefano Zampini     }
4809674ae819SStefano Zampini   }
4810dc456d91SStefano Zampini 
4811dc456d91SStefano Zampini   /* from roots to leaves */
4812dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4813dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4814dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4815dc456d91SStefano Zampini 
4816dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4817dc456d91SStefano Zampini   if (subset_mult) {
4818dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4819dc456d91SStefano Zampini     PetscInt        cum;
4820dc456d91SStefano Zampini 
4821dc456d91SStefano Zampini     cum = 0;
4822dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4823dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4824dc456d91SStefano Zampini       PetscInt j;
4825dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4826674ae819SStefano Zampini     }
4827dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4828674ae819SStefano Zampini   } else {
4829dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4830dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4831674ae819SStefano Zampini     }
4832674ae819SStefano Zampini   }
4833dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4834dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4835674ae819SStefano Zampini   PetscFunctionReturn(0);
4836674ae819SStefano Zampini }
48379a7d3425SStefano Zampini 
48389a7d3425SStefano Zampini #undef __FUNCT__
48399a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
48409a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
48419a7d3425SStefano Zampini {
48429a7d3425SStefano Zampini   PetscInt       i,j;
48439a7d3425SStefano Zampini   PetscScalar    *alphas;
48449a7d3425SStefano Zampini   PetscErrorCode ierr;
48459a7d3425SStefano Zampini 
48469a7d3425SStefano Zampini   PetscFunctionBegin;
48479a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4848785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
48499a7d3425SStefano Zampini   for (i=0;i<n;i++) {
48509a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
48519a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
48529a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
48539a7d3425SStefano Zampini   }
48549a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
48559a7d3425SStefano Zampini   PetscFunctionReturn(0);
48569a7d3425SStefano Zampini }
48579a7d3425SStefano Zampini 
4858e7931f94SStefano Zampini #undef __FUNCT__
485970cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
486057de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
4861e7931f94SStefano Zampini {
486257de7509SStefano Zampini   Mat            A;
4863e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4864e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
486552e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
486652e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
486727b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
486857de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
486927b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
487027b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
487127b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
487227b6a85dSStefano Zampini   MPI_Comm       subcomm;
487352e5ac9dSStefano Zampini   PetscErrorCode ierr;
4874a57a6d2fSStefano Zampini 
4875e7931f94SStefano Zampini   PetscFunctionBegin;
487657de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
487757de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
487857de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
487957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
488057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
488157de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
488257de7509SStefano Zampini 
488357de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
488457de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
488557de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
488657de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
488757de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
488857de7509SStefano Zampini   im_active = !!(n);
488957de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
489057de7509SStefano Zampini   void_procs = size - active_procs;
489157de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
489257de7509SStefano Zampini   if (void_procs) {
489357de7509SStefano Zampini     PetscInt ncand;
489457de7509SStefano Zampini 
489557de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
489657de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
489757de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
489857de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
489957de7509SStefano Zampini       if (!procs_candidates[i]) {
490057de7509SStefano Zampini         procs_candidates[ncand++] = i;
490157de7509SStefano Zampini       }
490257de7509SStefano Zampini     }
490357de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
490457de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
490557de7509SStefano Zampini   }
490657de7509SStefano Zampini 
490757de7509SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix */
490857de7509SStefano Zampini   if (active_procs < *n_subdomains) {
490957de7509SStefano Zampini     PetscInt issize,isidx;
491057de7509SStefano Zampini     if (im_active) {
491157de7509SStefano Zampini       issize = 1;
491257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
491357de7509SStefano Zampini         isidx = procs_candidates[rank];
491457de7509SStefano Zampini       } else {
491557de7509SStefano Zampini         isidx = rank;
491657de7509SStefano Zampini       }
491757de7509SStefano Zampini     } else {
491857de7509SStefano Zampini       issize = 0;
491957de7509SStefano Zampini       isidx = -1;
492057de7509SStefano Zampini     }
492157de7509SStefano Zampini     *n_subdomains = active_procs;
492257de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
4923daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
492457de7509SStefano Zampini     PetscFunctionReturn(0);
492557de7509SStefano Zampini   }
4926c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
4927c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
492827b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
4929e7931f94SStefano Zampini 
4930e7931f94SStefano Zampini   /* Get info on mapping */
49313bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
49323bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4933e7931f94SStefano Zampini 
4934e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4935785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4936e7931f94SStefano Zampini   xadj[0] = 0;
4937e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4938785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4939785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
494027b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
494127b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
494227b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
494327b6a85dSStefano Zampini       count[shared[i][j]] += 1;
4944e7931f94SStefano Zampini 
494527b6a85dSStefano Zampini   xadj_count = 0;
49462b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
494727b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
494827b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
4949d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4950d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4951d023bfaeSStefano Zampini         xadj_count++;
495227b6a85dSStefano Zampini         break;
495327b6a85dSStefano Zampini       }
4954e7931f94SStefano Zampini     }
4955e7931f94SStefano Zampini   }
4956d023bfaeSStefano Zampini   xadj[1] = xadj_count;
495727b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
49583bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4959e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4960e7931f94SStefano Zampini 
49613837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4962e7931f94SStefano Zampini 
496327b6a85dSStefano Zampini   /* Restrict work on active processes only */
496427b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
496527b6a85dSStefano Zampini   if (void_procs) {
496627b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
496727b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
496827b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
496927b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
497027b6a85dSStefano Zampini   } else {
497127b6a85dSStefano Zampini     psubcomm = NULL;
497227b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
497327b6a85dSStefano Zampini   }
497427b6a85dSStefano Zampini 
497527b6a85dSStefano Zampini   v_wgt = NULL;
497627b6a85dSStefano Zampini   if (!color) {
4977e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4978e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4979e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4980c8587f34SStefano Zampini   } else {
498152e5ac9dSStefano Zampini     Mat             subdomain_adj;
498252e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
498352e5ac9dSStefano Zampini     MatPartitioning partitioner;
498427b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
498552e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
498657de7509SStefano Zampini     PetscMPIInt     size;
4987b0c7d250SStefano Zampini     PetscBool       aggregate;
4988b0c7d250SStefano Zampini 
498927b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
499027b6a85dSStefano Zampini     if (void_procs) {
499127b6a85dSStefano Zampini       PetscInt prank = rank;
4992785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
499327b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
4994e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
4995e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4996c8587f34SStefano Zampini       }
4997e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
499827b6a85dSStefano Zampini     } else {
499927b6a85dSStefano Zampini       oldranks = NULL;
500027b6a85dSStefano Zampini     }
5001b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
500227b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
5003b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
5004b0c7d250SStefano Zampini       PetscMPIInt nrank;
5005b0c7d250SStefano Zampini       PetscScalar *vals;
5006b0c7d250SStefano Zampini 
500727b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
5008b0c7d250SStefano Zampini       lrows = 0;
5009b0c7d250SStefano Zampini       if (nrank<redprocs) {
5010b0c7d250SStefano Zampini         lrows = size/redprocs;
5011b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
5012b0c7d250SStefano Zampini       }
501327b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
5014b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
5015b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5016b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5017b0c7d250SStefano Zampini       row = nrank;
5018b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
5019b0c7d250SStefano Zampini       cols = adjncy;
5020b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
5021b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5022b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5023b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5024b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
502552e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
502652e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
502752e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5028b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
502927b6a85dSStefano Zampini       if (use_vwgt) {
503027b6a85dSStefano Zampini         Vec               v;
503127b6a85dSStefano Zampini         const PetscScalar *array;
503227b6a85dSStefano Zampini         PetscInt          nl;
503327b6a85dSStefano Zampini 
503427b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
503527b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
503627b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
503727b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
503827b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
503927b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
504027b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
504122db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
504227b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
504327b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
504427b6a85dSStefano Zampini       }
5045b0c7d250SStefano Zampini     } else {
504627b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
504727b6a85dSStefano Zampini       if (use_vwgt) {
504827b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
504927b6a85dSStefano Zampini         v_wgt[0] = local_size;
505027b6a85dSStefano Zampini       }
5051b0c7d250SStefano Zampini     }
505222b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5053e7931f94SStefano Zampini 
5054e7931f94SStefano Zampini     /* Partition */
505527b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5056e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
505727b6a85dSStefano Zampini     if (v_wgt) {
5058e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5059c8587f34SStefano Zampini     }
506057de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
506157de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5062e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5063e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
506422b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5065e7931f94SStefano Zampini 
506652e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
506752e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
506852e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
506952e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
507057de7509SStefano Zampini     if (!aggregate) {
507157de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
507227b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
507327b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
507427b6a85dSStefano Zampini #endif
507557de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
507627b6a85dSStefano Zampini       } else if (oldranks) {
5077b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
507827b6a85dSStefano Zampini       } else {
507927b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
508057de7509SStefano Zampini       }
508128143c3dSStefano Zampini     } else {
5082b0c7d250SStefano Zampini       PetscInt    idxs[1];
5083b0c7d250SStefano Zampini       PetscMPIInt tag;
5084b0c7d250SStefano Zampini       MPI_Request *reqs;
5085b0c7d250SStefano Zampini 
5086b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5087b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5088b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
508927b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
509028143c3dSStefano Zampini       }
509127b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5092b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5093b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
509457de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
509527b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
509627b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
509727b6a85dSStefano Zampini #endif
509857de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
509927b6a85dSStefano Zampini       } else if (oldranks) {
5100b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
510127b6a85dSStefano Zampini       } else {
510227b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5103e7931f94SStefano Zampini       }
510457de7509SStefano Zampini     }
510552e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5106e7931f94SStefano Zampini     /* clean up */
5107e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
510852e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5109e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5110e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5111e7931f94SStefano Zampini   }
511227b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
511357de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5114e7931f94SStefano Zampini 
5115e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5116e7931f94SStefano Zampini   i = 1;
511727b6a85dSStefano Zampini   if (!color) i=0;
511857de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5119e7931f94SStefano Zampini   PetscFunctionReturn(0);
5120e7931f94SStefano Zampini }
5121e7931f94SStefano Zampini 
5122e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5123e7931f94SStefano Zampini 
5124e7931f94SStefano Zampini #undef __FUNCT__
5125e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
512657de7509SStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, PetscBool restrict_full, PetscBool reuse, Mat *mat_n, PetscInt nis, IS isarray[])
5127e7931f94SStefano Zampini {
512870cf5478SStefano Zampini   Mat                    local_mat;
5129e7931f94SStefano Zampini   IS                     is_sends_internal;
51309d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
513128143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
51329d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
5133e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
5134e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
5135e7931f94SStefano Zampini   const PetscInt*        is_indices;
5136e7931f94SStefano Zampini   MatType                new_local_type;
5137e7931f94SStefano Zampini   /* buffers */
5138e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
513928143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
51409d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
5141e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
5142e7931f94SStefano Zampini   /* MPI */
514328143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
514428143c3dSStefano Zampini   PetscSubcomm           subcomm;
5145e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
514628143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
514728143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
514828143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
514928143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
515028143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
5151e7931f94SStefano Zampini   PetscErrorCode         ierr;
5152e7931f94SStefano Zampini 
5153e7931f94SStefano Zampini   PetscFunctionBegin;
515457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5155e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
515628143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
515757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
515857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
515957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
516057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
516157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
516257de7509SStefano Zampini 
516357de7509SStefano Zampini   /* further checks */
5164e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5165e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5166e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
5167e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
5168e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
516957de7509SStefano Zampini   if (reuse && *mat_n) {
517070cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
517157de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
517270cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
517328143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
517470cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
517570cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
517670cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
517770cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
517870cf5478SStefano Zampini   }
5179e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
5180e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
518157de7509SStefano Zampini 
5182e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
5183e7931f94SStefano Zampini   if (!is_sends) {
518428143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
518557de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
5186c8587f34SStefano Zampini   } else {
5187e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
5188e7931f94SStefano Zampini     is_sends_internal = is_sends;
5189c8587f34SStefano Zampini   }
5190e7931f94SStefano Zampini 
5191e7931f94SStefano Zampini   /* get comm */
5192a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
5193e7931f94SStefano Zampini 
5194e7931f94SStefano Zampini   /* compute number of sends */
5195e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
5196e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
5197e7931f94SStefano Zampini 
5198e7931f94SStefano Zampini   /* compute number of receives */
5199e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
5200785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
5201e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
5202e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5203e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
5204e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
5205e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
5206e7931f94SStefano Zampini 
520728143c3dSStefano Zampini   /* restrict comm if requested */
520828143c3dSStefano Zampini   subcomm = 0;
520928143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
521028143c3dSStefano Zampini   if (restrict_comm) {
5211779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
5212779c1cceSStefano Zampini 
521328143c3dSStefano Zampini     color = 0;
521453a05cb3SStefano Zampini     if (restrict_full) {
521553a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
521653a05cb3SStefano Zampini     } else {
521753a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
521853a05cb3SStefano Zampini     }
5219b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
522028143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
522128143c3dSStefano Zampini     /* check if reuse has been requested */
522257de7509SStefano Zampini     if (reuse) {
522328143c3dSStefano Zampini       if (*mat_n) {
522428143c3dSStefano Zampini         PetscMPIInt subcommsize2;
522528143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
522628143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
522728143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
522828143c3dSStefano Zampini       } else {
522928143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
523028143c3dSStefano Zampini       }
523128143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
5232779c1cceSStefano Zampini       PetscMPIInt rank;
5233779c1cceSStefano Zampini 
5234779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
523528143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
523628143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
523728143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
5238306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
523928143c3dSStefano Zampini     }
524028143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
524128143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
524228143c3dSStefano Zampini   } else {
524328143c3dSStefano Zampini     comm_n = comm;
524428143c3dSStefano Zampini   }
524528143c3dSStefano Zampini 
5246e7931f94SStefano Zampini   /* prepare send/receive buffers */
5247785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
5248e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
5249785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
5250e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
525128143c3dSStefano Zampini   if (nis) {
5252854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
525328143c3dSStefano Zampini   }
5254e7931f94SStefano Zampini 
525528143c3dSStefano Zampini   /* Get data from local matrices */
52566c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
5257e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
5258e7931f94SStefano Zampini     /*
5259e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
5260e7931f94SStefano Zampini        send_buffer_idxs should contain:
5261e7931f94SStefano Zampini        - MatType_PRIVATE type
5262e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
5263e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
5264e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
5265e7931f94SStefano Zampini     */
52666c4ed002SBarry Smith   else {
5267e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
52683bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
5269854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
5270e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
5271e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
52723bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5273e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
52743bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5275e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
5276e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
5277e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
5278e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
5279c8587f34SStefano Zampini     }
5280c8587f34SStefano Zampini   }
5281e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
528228143c3dSStefano Zampini   /* additional is (if any) */
528328143c3dSStefano Zampini   if (nis) {
528428143c3dSStefano Zampini     PetscMPIInt psum;
528528143c3dSStefano Zampini     PetscInt j;
528628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
528728143c3dSStefano Zampini       PetscInt plen;
528828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
528928143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
529028143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
529128143c3dSStefano Zampini     }
5292854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
529328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
529428143c3dSStefano Zampini       PetscInt plen;
529528143c3dSStefano Zampini       const PetscInt *is_array_idxs;
529628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
529728143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
529828143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
529928143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
530028143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
530128143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
530228143c3dSStefano Zampini     }
530328143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
530428143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
530528143c3dSStefano Zampini     }
530628143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
530728143c3dSStefano Zampini   }
530828143c3dSStefano Zampini 
5309e7931f94SStefano Zampini   buf_size_idxs = 0;
5310e7931f94SStefano Zampini   buf_size_vals = 0;
531128143c3dSStefano Zampini   buf_size_idxs_is = 0;
5312e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5313e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
5314e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
531528143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
5316e7931f94SStefano Zampini   }
5317785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
5318785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
531995ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
5320e7931f94SStefano Zampini 
5321e7931f94SStefano Zampini   /* get new tags for clean communications */
5322e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
5323e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
532428143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
5325e7931f94SStefano Zampini 
5326e7931f94SStefano Zampini   /* allocate for requests */
5327785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
5328785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
532995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
5330785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
5331785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
533295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
5333e7931f94SStefano Zampini 
5334e7931f94SStefano Zampini   /* communications */
5335e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
5336e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
533728143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
5338e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5339e7931f94SStefano Zampini     source_dest = onodes[i];
5340e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
5341e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
5342e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5343e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
534428143c3dSStefano Zampini     if (nis) {
534557de7509SStefano Zampini       source_dest = onodes_is[i];
534628143c3dSStefano 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);
534728143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
534828143c3dSStefano Zampini     }
5349e7931f94SStefano Zampini   }
5350e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
5351e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
5352e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
5353e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
535428143c3dSStefano Zampini     if (nis) {
535528143c3dSStefano 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);
535628143c3dSStefano Zampini     }
5357e7931f94SStefano Zampini   }
5358e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5359e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
5360e7931f94SStefano Zampini 
5361e7931f94SStefano Zampini   /* assemble new l2g map */
5362e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5363e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
53649d30be91SStefano Zampini   new_local_rows = 0;
5365e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
53669d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5367e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5368e7931f94SStefano Zampini   }
53699d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
5370e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
53719d30be91SStefano Zampini   new_local_rows = 0;
5372e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
53739d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
53749d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5375e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5376e7931f94SStefano Zampini   }
53779d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
53789d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
5379e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
5380e7931f94SStefano Zampini 
5381e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
5382e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
5383e7931f94SStefano 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) */
5384e7931f94SStefano Zampini   if (n_recvs) {
538528143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
5386e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
5387e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
5388e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
5389e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
5390e7931f94SStefano Zampini         break;
5391e7931f94SStefano Zampini       }
5392e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
5393e7931f94SStefano Zampini     }
5394e7931f94SStefano Zampini     switch (new_local_type_private) {
539528143c3dSStefano Zampini       case MATDENSE_PRIVATE:
539628143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
5397e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
5398e7931f94SStefano Zampini           bs = 1;
539928143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
540028143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
540128143c3dSStefano Zampini           bs = 1;
540228143c3dSStefano Zampini         }
5403e7931f94SStefano Zampini         break;
5404e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
5405e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
5406e7931f94SStefano Zampini         bs = 1;
5407e7931f94SStefano Zampini         break;
5408e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
5409e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
5410e7931f94SStefano Zampini         break;
5411e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
5412e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
5413e7931f94SStefano Zampini         break;
5414e7931f94SStefano Zampini       default:
54159d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
5416e7931f94SStefano Zampini         break;
5417e7931f94SStefano Zampini     }
541828143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
541928143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
542028143c3dSStefano Zampini     bs = 1;
5421e7931f94SStefano Zampini   }
5422e7931f94SStefano Zampini 
542370cf5478SStefano Zampini   /* create MATIS object if needed */
542457de7509SStefano Zampini   if (!reuse) {
5425e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
5426e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
542770cf5478SStefano Zampini   } else {
542870cf5478SStefano Zampini     /* it also destroys the local matrices */
542957de7509SStefano Zampini     if (*mat_n) {
543070cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
543157de7509SStefano Zampini     } else { /* this is a fake object */
543257de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
543357de7509SStefano Zampini     }
543470cf5478SStefano Zampini   }
543570cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
5436e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
54379d30be91SStefano Zampini 
54389d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
54399d30be91SStefano Zampini 
54409d30be91SStefano Zampini   /* Global to local map of received indices */
54419d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
54429d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
54439d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
54449d30be91SStefano Zampini 
54459d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
54469d30be91SStefano Zampini   buf_size_idxs = 0;
54479d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
54489d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
54499d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
54509d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
54519d30be91SStefano Zampini   }
54529d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
54539d30be91SStefano Zampini 
54549d30be91SStefano Zampini   /* set preallocation */
54559d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
54569d30be91SStefano Zampini   if (!newisdense) {
54579d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
54589d30be91SStefano Zampini 
54599d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
54609d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
54619d30be91SStefano Zampini     if (n_recvs) {
54629d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
54639d30be91SStefano Zampini     }
54649d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
54659d30be91SStefano Zampini       PetscInt j;
54669d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
54679d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
54689d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
54699d30be91SStefano Zampini         }
54709d30be91SStefano Zampini       } else {
54719d30be91SStefano Zampini         /* TODO */
54729d30be91SStefano Zampini       }
54739d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
54749d30be91SStefano Zampini     }
54759d30be91SStefano Zampini     if (new_local_nnz) {
54769d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
54779d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
54789d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
54799d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
54809d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
54819d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
54829d30be91SStefano Zampini     } else {
54839d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
54849d30be91SStefano Zampini     }
54859d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
54869d30be91SStefano Zampini   } else {
54879d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
54889d30be91SStefano Zampini   }
5489e7931f94SStefano Zampini 
5490e7931f94SStefano Zampini   /* set values */
5491e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
54929d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5493e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5494e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5495e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
54969d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5497e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5498e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5499e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
550028143c3dSStefano Zampini     } else {
550128143c3dSStefano Zampini       /* TODO */
5502e7931f94SStefano Zampini     }
5503e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5504e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5505e7931f94SStefano Zampini   }
5506e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5507e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
550870cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
550970cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55109d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
55119d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5512e7931f94SStefano Zampini 
5513dfd14d43SStefano Zampini #if 0
551428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5515e7931f94SStefano Zampini     Vec       lvec,rvec;
5516e7931f94SStefano Zampini     PetscReal infty_error;
5517e7931f94SStefano Zampini 
55182a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5519e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5520e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5521e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
552270cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5523e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5524e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5525e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5526e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5527e7931f94SStefano Zampini   }
552828143c3dSStefano Zampini #endif
5529e7931f94SStefano Zampini 
553028143c3dSStefano Zampini   /* assemble new additional is (if any) */
553128143c3dSStefano Zampini   if (nis) {
553228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
553328143c3dSStefano Zampini 
553428143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5535854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
553628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
553728143c3dSStefano Zampini     psum = 0;
553828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
553928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
554028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
554128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
554228143c3dSStefano Zampini         psum += plen;
554328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
554428143c3dSStefano Zampini       }
554528143c3dSStefano Zampini     }
5546854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5547854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
554828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
554928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
555028143c3dSStefano Zampini     }
555128143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
555228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
555328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
555428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
555528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
555628143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
555728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
555828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
555928143c3dSStefano Zampini       }
556028143c3dSStefano Zampini     }
556128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
556228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
556328143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
556428143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
556528143c3dSStefano Zampini     }
556628143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
556728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
556828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
556928143c3dSStefano Zampini   }
5570e7931f94SStefano Zampini   /* free workspace */
557128143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5572e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5573e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5574e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5575e7931f94SStefano Zampini   if (isdense) {
5576e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5577e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5578e7931f94SStefano Zampini   } else {
5579e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5580e7931f94SStefano Zampini   }
558128143c3dSStefano Zampini   if (nis) {
558228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
558328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
558428143c3dSStefano Zampini   }
5585e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5586e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
558728143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5588e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5589e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
559028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5591e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5592e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5593e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5594e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5595e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
559628143c3dSStefano Zampini   if (nis) {
559728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
559828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
559928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
560028143c3dSStefano Zampini   }
560128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
560228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
560328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
560428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
560528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
560628143c3dSStefano Zampini     }
560753a05cb3SStefano Zampini     *mat_n = NULL;
560828143c3dSStefano Zampini   }
5609e7931f94SStefano Zampini   PetscFunctionReturn(0);
5610e7931f94SStefano Zampini }
5611a57a6d2fSStefano Zampini 
561212edc857SStefano Zampini /* temporary hack into ksp private data structure */
5613af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
561412edc857SStefano Zampini 
5615c8587f34SStefano Zampini #undef __FUNCT__
5616c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5617c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5618c8587f34SStefano Zampini {
5619c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5620c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
562120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
56229881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
562320a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
56246e683305SStefano Zampini   IS                     coarse_is,*isarray;
56256e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
562630368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5627f9eb5b7dSStefano Zampini   PC                     pc_temp;
5628c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5629c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5630f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
56314f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
56326e683305SStefano Zampini   Mat                    t_coarse_mat_is;
563357de7509SStefano Zampini   PetscInt               ncoarse;
563468457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
563522bc73bbSStefano Zampini   PetscScalar            *array;
563657de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
563757de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
56389881197aSStefano Zampini   PetscErrorCode         ierr;
5639fdc09c96SStefano Zampini 
5640c8587f34SStefano Zampini   PetscFunctionBegin;
5641c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
564268457ee5SStefano 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 */
5643fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
56445a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5645fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5646f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5647f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5648f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5649fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
565051bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
565151bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5652dc4bcba2SStefano Zampini         PC        pc;
5653dc4bcba2SStefano Zampini         PetscBool isbddc;
5654dc4bcba2SStefano Zampini 
5655dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5656dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5657dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5658dc4bcba2SStefano Zampini         if (isbddc) {
565963c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
566063c961adSStefano Zampini         } else {
5661727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
566263c961adSStefano Zampini         }
5663fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5664fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5665fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5666f4ddd8eeSStefano Zampini       }
5667fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5668fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5669f4ddd8eeSStefano Zampini     }
567070cf5478SStefano Zampini     /* reset any subassembling information */
567157de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
567270cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
567357de7509SStefano Zampini     }
56746e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5675fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5676f4ddd8eeSStefano Zampini   }
567757de7509SStefano Zampini   /* assemble coarse matrix */
567857de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
567957de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
568057de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
568157de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
568218a45a71SStefano Zampini   } else {
568357de7509SStefano Zampini     coarse_mat = NULL;
568457de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
56856e683305SStefano Zampini   }
5686e7931f94SStefano Zampini 
5687abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5688abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5689abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5690abbbba34SStefano Zampini 
5691abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
569222bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
569322bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
569422bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
569522bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5696e176bc59SStefano 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);
56976e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
56986e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
56996e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5700abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5701abbbba34SStefano Zampini 
570257de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
570357de7509SStefano Zampini   im_active = !!(pcis->n);
570457de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
570557de7509SStefano Zampini 
570657de7509SStefano Zampini   /* determine number of process partecipating to coarse solver and compute subassembling pattern */
570757de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
570857de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
570957de7509SStefano Zampini   coarse_mat_is = NULL;
571057de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
571157de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
571257de7509SStefano Zampini   full_restr = PETSC_TRUE;
571357de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(pcbddc->coarse_size,pcbddc->coarse_eqs_per_proc);
571457de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
571557de7509SStefano Zampini   if (multilevel_requested) {
571657de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
571757de7509SStefano Zampini     restr = PETSC_FALSE;
571857de7509SStefano Zampini     full_restr = PETSC_FALSE;
571957de7509SStefano Zampini   } else {
572057de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
572157de7509SStefano Zampini     restr = PETSC_TRUE;
572257de7509SStefano Zampini     full_restr = PETSC_TRUE;
572357de7509SStefano Zampini   }
572457de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
572557de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
572657de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
572757de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
572857de7509SStefano Zampini     PetscInt    psum;
572957de7509SStefano Zampini     PetscMPIInt size;
573057de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
573157de7509SStefano Zampini     else psum = 0;
573257de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
573357de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
573457de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
573557de7509SStefano Zampini   }
573657de7509SStefano Zampini   /* determine if we can go multilevel */
573757de7509SStefano Zampini   if (multilevel_requested) {
573857de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
573957de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
574057de7509SStefano Zampini   }
574157de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
574257de7509SStefano Zampini 
5743e4d548c7SStefano Zampini   /* dump subassembling pattern */
5744e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
5745e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
5746e4d548c7SStefano Zampini   }
5747e4d548c7SStefano Zampini 
57486e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
574927b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
57506e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
57516e683305SStefano Zampini     const PetscInt         *idxs;
57526e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
57536e683305SStefano Zampini 
57546e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
57550be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
57566e683305SStefano Zampini     /* allocate space for temporary storage */
5757854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5758854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
57596e683305SStefano Zampini     /* allocate for IS array */
57606e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
57616e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
576227b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
576330368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5764854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
57656e683305SStefano Zampini     /* dofs splitting */
57666e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
57676e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
57686e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
57696e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
57706e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
57716e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
57726e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
577330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
57746e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
57756e683305SStefano Zampini     }
57766e683305SStefano Zampini     /* neumann boundaries */
57776e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
57786e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
57796e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
57806e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
57816e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
57826e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
57836e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
578430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
57856e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
57866e683305SStefano Zampini     }
57876e683305SStefano Zampini     /* free memory */
57886e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
57896e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
57906e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
57916e683305SStefano Zampini   } else {
57926e683305SStefano Zampini     nis = 0;
57936e683305SStefano Zampini     nisdofs = 0;
57946e683305SStefano Zampini     nisneu = 0;
579530368db7SStefano Zampini     nisvert = 0;
57966e683305SStefano Zampini     isarray = NULL;
57976e683305SStefano Zampini   }
57986e683305SStefano Zampini   /* destroy no longer needed map */
57996e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
58006e683305SStefano Zampini 
580157de7509SStefano Zampini   /* subassemble */
580257de7509SStefano Zampini   if (multilevel_allowed) {
580357de7509SStefano Zampini     PetscBool reuse,reuser;
580457de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
580557de7509SStefano Zampini     else reuse = PETSC_FALSE;
580657de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
580757de7509SStefano Zampini     if (reuser) {
580857de7509SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray);CHKERRQ(ierr);
580974e2c79eSStefano Zampini     } else {
581057de7509SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
581174e2c79eSStefano Zampini     }
5812*1f4df5f7SStefano Zampini     /* TODO: if (pcbddc->benign_have_null) -> give a hint to the coarser levels if they have to locally apply the benign trick or not */
581374e2c79eSStefano Zampini   } else {
581457de7509SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
58156e683305SStefano Zampini   }
581657de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
581757de7509SStefano Zampini     PetscMPIInt size;
581857de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
581957de7509SStefano Zampini     if (!multilevel_allowed) {
582057de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
58216e683305SStefano Zampini     } else {
582257de7509SStefano Zampini       Mat A;
5823779c1cceSStefano Zampini 
582457de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
582557de7509SStefano Zampini       if (coarse_mat_is) {
582657de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
582757de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
582857de7509SStefano Zampini         coarse_mat = coarse_mat_is;
582957de7509SStefano Zampini       }
583057de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
583157de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
583257de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
5833779c1cceSStefano Zampini     }
5834779c1cceSStefano Zampini   }
583557de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
583657de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
58376e683305SStefano Zampini 
58386e683305SStefano Zampini   /* create local to global scatters for coarse problem */
583968457ee5SStefano Zampini   if (compute_vecs) {
58406e683305SStefano Zampini     PetscInt lrows;
58416e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
584257de7509SStefano Zampini     if (coarse_mat) {
584357de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
58446e683305SStefano Zampini     } else {
58456e683305SStefano Zampini       lrows = 0;
58466e683305SStefano Zampini     }
58476e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
58486e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
58496e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
58506e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
58516e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
58526e683305SStefano Zampini   }
58536e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
5854c8587f34SStefano Zampini 
5855f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5856f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5857f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5858f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5859f9eb5b7dSStefano Zampini   } else {
5860f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5861f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5862c8587f34SStefano Zampini   }
5863c8587f34SStefano Zampini 
58646e683305SStefano Zampini   /* print some info if requested */
58656e683305SStefano Zampini   if (pcbddc->dbg_flag) {
58666e683305SStefano Zampini     if (!multilevel_allowed) {
58676e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
58686e683305SStefano Zampini       if (multilevel_requested) {
58696e683305SStefano 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);
58706e683305SStefano Zampini       } else if (pcbddc->max_levels) {
58716e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
58726e683305SStefano Zampini       }
58736e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
58746e683305SStefano Zampini     }
58756e683305SStefano Zampini   }
58766e683305SStefano Zampini 
5877f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
587857de7509SStefano Zampini   if (coarse_mat) {
58796a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
58806e683305SStefano Zampini     if (pcbddc->dbg_flag) {
588157de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
58826e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
58836e683305SStefano Zampini     }
5884f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5885312be037SStefano Zampini       char prefix[256],str_level[16];
5886e604994aSStefano Zampini       size_t len;
588757de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5888422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5889c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5890f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
589157de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5892c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
58936e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5894c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5895c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5896e604994aSStefano Zampini       /* prefix */
5897e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5898e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5899e604994aSStefano Zampini       if (!pcbddc->current_level) {
5900e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5901e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5902c8587f34SStefano Zampini       } else {
5903e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5904312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5905312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
590634d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5907312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5908e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5909e604994aSStefano Zampini       }
5910e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
59113e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
59123e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
59133e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
59143e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5915f9eb5b7dSStefano Zampini       /* allow user customization */
5916f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
59173e3c6dadSStefano Zampini     }
59183e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
591951bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
59203e3c6dadSStefano Zampini     if (nisdofs) {
59213e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
59223e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
59233e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
59243e3c6dadSStefano Zampini       }
59253e3c6dadSStefano Zampini     }
59263e3c6dadSStefano Zampini     if (nisneu) {
59273e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
59283e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5929312be037SStefano Zampini     }
593030368db7SStefano Zampini     if (nisvert) {
593130368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
593230368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
593330368db7SStefano Zampini     }
5934f9eb5b7dSStefano Zampini 
5935f9eb5b7dSStefano Zampini     /* get some info after set from options */
5936f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5937f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
59384f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
59396e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5940f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5941f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5942f9eb5b7dSStefano Zampini     }
594339f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
59444f3a063dSStefano Zampini     if (isredundant) {
59454f3a063dSStefano Zampini       KSP inner_ksp;
59464f3a063dSStefano Zampini       PC  inner_pc;
59474f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
59484f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
59494f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
59504f3a063dSStefano Zampini     }
5951f9eb5b7dSStefano Zampini 
595257de7509SStefano Zampini     /* parameters which miss an API */
595357de7509SStefano Zampini     if (isbddc) {
5954720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
5955720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
595657de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
595727b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
595827b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
595927b6a85dSStefano Zampini         pcbddc_coarse->benign_compute_nonetflux = PETSC_TRUE;
5960720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
596159e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
5962720d30f9SStefano Zampini       }
5963d4d8cf7bSStefano Zampini     }
59649881197aSStefano Zampini 
59653301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
59665a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
59673301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
59683301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
59693301b35fSStefano Zampini     }
59703301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
59713301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
59723301b35fSStefano Zampini     }
59733301b35fSStefano Zampini     if (pc->pmat->spd_set) {
59743301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
59753301b35fSStefano Zampini     }
597627b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
597727b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
597827b6a85dSStefano Zampini     }
59796e683305SStefano Zampini     /* set operators */
59805f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
59816e683305SStefano Zampini     if (pcbddc->dbg_flag) {
59826e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
59836e683305SStefano Zampini     }
59846e683305SStefano Zampini   }
59856e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
5986b1ecc7b1SStefano Zampini #if 0
5987b9b85e73SStefano Zampini   {
5988b9b85e73SStefano Zampini     PetscViewer viewer;
5989b9b85e73SStefano Zampini     char filename[256];
5990b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
5991b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
59926a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5993b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
5994f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
5995b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5996b9b85e73SStefano Zampini   }
5997b9b85e73SStefano Zampini #endif
5998f9eb5b7dSStefano Zampini 
5999b8ffe317SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
6000298c0119SStefano Zampini #if 0
6001b8ffe317SStefano Zampini   if (pcbddc->NullSpace) {
6002b8ffe317SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
600398a51de6SStefano Zampini   }
6004298c0119SStefano Zampini #endif
6005b0f5fe93SStefano Zampini   /* hack */
600698a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
600798a51de6SStefano Zampini     Vec crhs,csol;
600804708bb6SStefano Zampini 
6009f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
6010f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
6011f347579bSStefano Zampini     if (!csol) {
60122a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
6013f9eb5b7dSStefano Zampini     }
6014f347579bSStefano Zampini     if (!crhs) {
60152a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
6016f347579bSStefano Zampini     }
6017b0f5fe93SStefano Zampini   }
6018b0f5fe93SStefano Zampini 
6019b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
6020b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
6021b0f5fe93SStefano Zampini 
6022b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
60234f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
60244f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
60254f1b2e48SStefano Zampini     }
6026b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
6027b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
6028b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6029b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6030b0f5fe93SStefano Zampini     if (coarse_mat) {
6031b0f5fe93SStefano Zampini       Vec         nullv;
6032b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
6033b0f5fe93SStefano Zampini       PetscInt    nl;
6034b0f5fe93SStefano Zampini 
6035b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
6036b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
6037b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6038b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
6039b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
6040b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
6041b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6042b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
6043b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
6044b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
6045b0f5fe93SStefano Zampini     }
6046b0f5fe93SStefano Zampini   }
6047b0f5fe93SStefano Zampini 
6048b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
6049b0f5fe93SStefano Zampini     PetscBool ispreonly;
6050b0f5fe93SStefano Zampini 
6051b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
6052b0f5fe93SStefano Zampini       PetscBool isnull;
6053b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
605427b6a85dSStefano Zampini       if (0) {
605530368db7SStefano Zampini         if (isbddc && !pcbddc->benign_saddle_point) {
6056b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
6057b0f5fe93SStefano Zampini         } else {
6058b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
6059b0f5fe93SStefano Zampini         }
6060b0f5fe93SStefano Zampini       } else {
6061b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6062b0f5fe93SStefano Zampini       }
6063b0f5fe93SStefano Zampini     }
6064b0f5fe93SStefano Zampini     /* setup coarse ksp */
6065b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
6066cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
6067cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
60686e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
6069c8587f34SStefano Zampini       KSP       check_ksp;
60702b510759SStefano Zampini       KSPType   check_ksp_type;
6071c8587f34SStefano Zampini       PC        check_pc;
60726e683305SStefano Zampini       Vec       check_vec,coarse_vec;
60736a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
60742b510759SStefano Zampini       PetscInt  its;
60756e683305SStefano Zampini       PetscBool compute_eigs;
60766e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
60776e683305SStefano Zampini       PetscInt  neigs;
60788e185a42SStefano Zampini       const char *prefix;
6079c8587f34SStefano Zampini 
60802b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
60816e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
6082422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
608323ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6084f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
6085e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
6086e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
6087e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
60882b510759SStefano Zampini       if (ispreonly) {
60892b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
60906e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
60912b510759SStefano Zampini       } else {
6092cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
60936e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
6094c8587f34SStefano Zampini       }
6095c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
60966e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
60976e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
60986e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
6099a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
6100a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
6101a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
6102a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
6103c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
6104c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
6105c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
6106c8587f34SStefano Zampini       /* create random vec */
61072701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
6108c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
6109c8587f34SStefano Zampini       if (CoarseNullSpace) {
6110c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
6111c8587f34SStefano Zampini       }
61126e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
6113c8587f34SStefano Zampini       /* solve coarse problem */
61146e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
6115c8587f34SStefano Zampini       if (CoarseNullSpace) {
61166e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
6117c8587f34SStefano Zampini       }
6118cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
61196e683305SStefano Zampini       if (compute_eigs) {
6120854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
6121854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
61226e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
61236e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
61246e683305SStefano Zampini         lambda_min = eigs_r[0];
61256e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
61262701bc32SStefano Zampini           if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
61272701bc32SStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
6128cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
6129cbcc2c2aSStefano Zampini           }
6130c8587f34SStefano Zampini         }
6131c8587f34SStefano Zampini       }
6132cbcc2c2aSStefano Zampini 
6133c8587f34SStefano Zampini       /* check coarse problem residual error */
61346e683305SStefano Zampini       if (pcbddc->dbg_flag) {
61356e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
61366e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
61376e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
6138c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
61396e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
61406e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
6141779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
61426e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
61436e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
61446e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
61456e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
6146b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
6147b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
6148b0f5fe93SStefano Zampini         }
61496e683305SStefano Zampini         if (compute_eigs) {
61506e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
6151deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
6152c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
61536e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
61546e683305SStefano 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);
61556e683305SStefano Zampini           for (i=0;i<neigs;i++) {
61566e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
6157c8587f34SStefano Zampini           }
61586e683305SStefano Zampini         }
61596e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
61606e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
61616e683305SStefano Zampini       }
6162e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
61632701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
6164c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
61656e683305SStefano Zampini       if (compute_eigs) {
61666e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
61676e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
6168c8587f34SStefano Zampini       }
61696e683305SStefano Zampini     }
61706e683305SStefano Zampini   }
6171cbcc2c2aSStefano Zampini   /* print additional info */
6172cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
61736e683305SStefano Zampini     /* waits until all processes reaches this point */
61746e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
6175cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
6176cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6177cbcc2c2aSStefano Zampini   }
6178cbcc2c2aSStefano Zampini 
61792b510759SStefano Zampini   /* free memory */
6180c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6181fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
6182c8587f34SStefano Zampini   PetscFunctionReturn(0);
6183c8587f34SStefano Zampini }
6184674ae819SStefano Zampini 
6185f34684f1SStefano Zampini #undef __FUNCT__
6186f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
6187f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
6188f34684f1SStefano Zampini {
6189f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6190f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
6191f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
6192dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
6193dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
619473be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
6195dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
6196f34684f1SStefano Zampini   PetscErrorCode ierr;
6197f34684f1SStefano Zampini 
6198f34684f1SStefano Zampini   PetscFunctionBegin;
6199f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
62006c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
6201dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
62023bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
6203dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6204dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
6205dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
6206dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
6207dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
6208dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
62096c4ed002SBarry Smith   if (local_size != pcbddc->local_primal_size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %D != %D",local_size,pcbddc->local_primal_size);
6210dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
6211dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6212dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
6213dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6214dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6215f34684f1SStefano Zampini 
6216f34684f1SStefano Zampini   /* check numbering */
6217f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
6218019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
6219dc456d91SStefano Zampini     PetscInt    i;
6220b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
6221f34684f1SStefano Zampini 
6222f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6223f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
6224f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
62251575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6226019a44ceSStefano Zampini     /* counter */
6227019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6228019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6229019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6230019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6231019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6232019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6233f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
6234f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
6235727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6236f34684f1SStefano Zampini     }
6237f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6238f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6239f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6240e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6241e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6242e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6243e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6244f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6245019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6246f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6247019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
62482c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
624975c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
6250b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
62512c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
62522c66d082SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d (gid %d) owned by %d processes instead of %d!\n",PetscGlobalRank,i,gi,owned,neigh);CHKERRQ(ierr);
6253f34684f1SStefano Zampini       }
6254f34684f1SStefano Zampini     }
6255019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6256b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
6257f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6258f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6259f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
6260f34684f1SStefano Zampini     }
6261f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6262f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6263e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6264e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6265f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
6266f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
6267b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
6268ca8b9ea9SStefano Zampini       PetscInt *gidxs;
6269ca8b9ea9SStefano Zampini 
6270ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
62713bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
6272f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
6273f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6274f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6275f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
62764bc2dc4bSStefano 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);
6277f34684f1SStefano Zampini       }
6278f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6279ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
6280f34684f1SStefano Zampini     }
6281f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
62821575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6283302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
6284f34684f1SStefano Zampini   }
62858bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
6286f34684f1SStefano Zampini   /* get back data */
6287f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
6288f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
6289674ae819SStefano Zampini   PetscFunctionReturn(0);
6290674ae819SStefano Zampini }
6291674ae819SStefano Zampini 
6292e456f2a8SStefano Zampini #undef __FUNCT__
6293e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
6294a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
6295e456f2a8SStefano Zampini {
6296e456f2a8SStefano Zampini   IS             localis_t;
6297a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
6298e456f2a8SStefano Zampini   PetscScalar    *vals;
6299e456f2a8SStefano Zampini   PetscErrorCode ierr;
6300e456f2a8SStefano Zampini 
6301e456f2a8SStefano Zampini   PetscFunctionBegin;
6302a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
6303e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
6304854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
6305e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
6306e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6307a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
6308a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
63091035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
6310a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
63111035eff8SStefano Zampini   }
6312a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
6313e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6314e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
6315a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
6316a7dc3881SStefano Zampini   /* now compute set in local ordering */
6317a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6318a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6319a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6320a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
6321a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6322ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6323e456f2a8SStefano Zampini       lsize++;
6324e456f2a8SStefano Zampini     }
6325e456f2a8SStefano Zampini   }
6326854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
6327a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6328ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6329e456f2a8SStefano Zampini       idxs[lsize++] = i;
6330e456f2a8SStefano Zampini     }
6331e456f2a8SStefano Zampini   }
6332a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6333a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
6334e456f2a8SStefano Zampini   *localis = localis_t;
6335e456f2a8SStefano Zampini   PetscFunctionReturn(0);
6336e456f2a8SStefano Zampini }
6337906d46d4SStefano Zampini 
6338b96c3477SStefano Zampini #undef __FUNCT__
6339b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
634008122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6341b96c3477SStefano Zampini {
6342a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6343b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6344b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6345a64f4aa4SStefano Zampini   Mat                 S_j;
6346b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6347b96c3477SStefano Zampini   PetscBool           free_used_adj;
6348b96c3477SStefano Zampini   PetscErrorCode      ierr;
6349b96c3477SStefano Zampini 
6350b96c3477SStefano Zampini   PetscFunctionBegin;
6351b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6352b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
635308122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6354b96c3477SStefano Zampini     used_xadj = NULL;
6355b96c3477SStefano Zampini     used_adjncy = NULL;
6356b96c3477SStefano Zampini   } else {
635708122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
635808122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
635908122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
636008122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6361b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6362b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6363b96c3477SStefano Zampini     } else {
63642fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6365b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6366b96c3477SStefano Zampini       PetscInt       nvtxs;
6367b96c3477SStefano Zampini 
63682fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
63692fffb893SStefano Zampini       if (flg_row) {
6370b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6371b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6372b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6373b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
63742fffb893SStefano Zampini       } else {
63752fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
63762fffb893SStefano Zampini         used_xadj = NULL;
63772fffb893SStefano Zampini         used_adjncy = NULL;
63782fffb893SStefano Zampini       }
63792fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6380b96c3477SStefano Zampini     }
6381b96c3477SStefano Zampini   }
6382d5574798SStefano Zampini 
6383d5574798SStefano Zampini   /* setup sub_schurs data */
6384a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6385df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6386df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6387a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
638891af6908SStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,NULL,S_j,PETSC_FALSE,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,NULL,pcbddc->adaptive_selection,PETSC_FALSE,PETSC_FALSE,0,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
6389a64f4aa4SStefano Zampini   } else {
63906816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
6391b7ab4a40SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;;
6392a3df083aSStefano Zampini     PetscInt  benign_n;
639372b8c272SStefano Zampini     Mat       change = NULL;
63949d54b7f4SStefano Zampini     Vec       scaling = NULL;
639572b8c272SStefano Zampini     IS        change_primal = NULL;
6396a3df083aSStefano Zampini 
63975feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
63985feab87aSStefano Zampini       PetscInt n_vertices;
63995feab87aSStefano Zampini 
64005feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
64012034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
64025feab87aSStefano Zampini     }
640304708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
640404708bb6SStefano Zampini     if (!isseqaij) {
640504708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
640604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
640704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
640804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
640904708bb6SStefano Zampini       } else {
6410511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
641104708bb6SStefano Zampini       }
641204708bb6SStefano Zampini     }
6413a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6414a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6415ca92afb2SStefano Zampini     } else {
6416a3df083aSStefano Zampini       benign_n = 0;
6417ca92afb2SStefano Zampini     }
6418b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
6419b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
6420b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
642172b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
642222db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
6423b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
642422db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
6425b7ab4a40SStefano Zampini     }
6426b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
6427b7ab4a40SStefano Zampini        We need to compute the change of basis according to the quadrature weights attached to pmat via MatSetNearNullSpace, and this could not be done (at the moment) without some hacking */
6428b7ab4a40SStefano Zampini     if (need_change) {
642988c03ad3SStefano Zampini       PC_IS   *pcisf;
643088c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
643188c03ad3SStefano Zampini       PC      pcf;
643288c03ad3SStefano Zampini 
6433e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
643488c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
643588c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
643688c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
643788c03ad3SStefano Zampini       /* hacks */
643888c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
643972b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
644072b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
644172b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
644272b8c272SStefano Zampini       pcisf->n = pcis->n;
644372b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
644488c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
644588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
644688c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
644788c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
644888c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
644988c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
645072b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
645188c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
645288c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
645372b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
645472b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
645572b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
645672b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
645772b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
645888c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
645972b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
646088c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
646188c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
646288c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
646388c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
646488c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
646588c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
646688c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
646788c03ad3SStefano Zampini     }
64689d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
646991af6908SStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,pcbddc->local_mat,S_j,pcbddc->sub_schurs_exact_schur,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,scaling,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point,benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_zerodiag_subs,change,change_primal);CHKERRQ(ierr);
647072b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
647172b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
6472ca92afb2SStefano Zampini   }
6473d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6474b96c3477SStefano Zampini 
6475b96c3477SStefano Zampini   /* free adjacency */
6476b96c3477SStefano Zampini   if (free_used_adj) {
6477b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6478b96c3477SStefano Zampini   }
6479b96c3477SStefano Zampini   PetscFunctionReturn(0);
6480b96c3477SStefano Zampini }
6481b96c3477SStefano Zampini 
6482b96c3477SStefano Zampini #undef __FUNCT__
6483b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
648408122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6485b96c3477SStefano Zampini {
6486b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6487b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6488b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6489b96c3477SStefano Zampini   PCBDDCGraph         graph;
6490b96c3477SStefano Zampini   PetscErrorCode      ierr;
6491b96c3477SStefano Zampini 
6492b96c3477SStefano Zampini   PetscFunctionBegin;
6493b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
649408122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
64953301b35fSStefano Zampini     IS       verticesIS,verticescomm;
64963301b35fSStefano Zampini     PetscInt vsize,*idxs;
6497b96c3477SStefano Zampini 
6498b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
64993301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
65003301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
65013301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
65023301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
65033301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6504b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
65057fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
6506441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
65073301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6508b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6509b96c3477SStefano Zampini   } else {
6510b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6511b96c3477SStefano Zampini   }
6512e4d548c7SStefano Zampini   /* print some info */
6513e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
6514e4d548c7SStefano Zampini     IS       vertices;
6515e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
6516e4d548c7SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6517e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
6518e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
6519e4d548c7SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
6520e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6521e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6522e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
6523e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
6524e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
6525e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6526e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6527e4d548c7SStefano Zampini   }
6528b96c3477SStefano Zampini 
6529b96c3477SStefano Zampini   /* sub_schurs init */
6530a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6531a64f4aa4SStefano Zampini 
6532b96c3477SStefano Zampini   /* free graph struct */
653308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6534b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6535b96c3477SStefano Zampini   }
6536b96c3477SStefano Zampini   PetscFunctionReturn(0);
6537b96c3477SStefano Zampini }
6538fa34dd3eSStefano Zampini 
6539fa34dd3eSStefano Zampini #undef __FUNCT__
6540fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6541fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6542fa34dd3eSStefano Zampini {
6543fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6544fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6545fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6546fa34dd3eSStefano Zampini 
6547fa34dd3eSStefano Zampini   PetscFunctionBegin;
6548fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6549fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
65504f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6551fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
65524f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
655375c01103SStefano Zampini     PetscReal      norm;
6554fa34dd3eSStefano Zampini     PetscInt       i;
6555fa34dd3eSStefano Zampini 
6556fa34dd3eSStefano Zampini     /* B0 and B0_B */
6557fa34dd3eSStefano Zampini     if (zerodiag) {
6558fa34dd3eSStefano Zampini       IS       dummy;
6559fa34dd3eSStefano Zampini 
65604f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
65614f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6562fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6563fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6564fa34dd3eSStefano Zampini     }
6565fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6566fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6567fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6568fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6569fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6570fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6571fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6572fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6573fa34dd3eSStefano Zampini     /* S_j */
6574fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6575fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6576fa34dd3eSStefano Zampini 
6577fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6578fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6579fa34dd3eSStefano Zampini     /* continuous in primal space */
6580fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6581fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6582fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6583fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
65844f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
65854f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6586fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6587fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6588fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6589fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6590fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6591fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6592fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6593fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6594fa34dd3eSStefano Zampini 
6595fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6596fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6597fa34dd3eSStefano Zampini     /* local with Schur */
6598fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6599fa34dd3eSStefano Zampini     if (zerodiag) {
6600fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
66014f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6602fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6603fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6604fa34dd3eSStefano Zampini     }
6605fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6606fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6607fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6608fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6609fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6610fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6611fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6612fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6613fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6614fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6615fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6616fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6617fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6618fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6619fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6620fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6621fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6622fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6623fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6624fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6625fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6626fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6627fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6628fa34dd3eSStefano Zampini     if (zerodiag) {
6629fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6630fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
66314f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6632fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6633fa34dd3eSStefano Zampini     }
6634fa34dd3eSStefano Zampini     /* BDDC */
6635fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6636fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6637fa34dd3eSStefano Zampini 
6638fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6639fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6640fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6641fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
66424f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
66434f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6644fa34dd3eSStefano Zampini     }
66454f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6646fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6647fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6648fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6649fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6650fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6651fa34dd3eSStefano Zampini   }
6652fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6653fa34dd3eSStefano Zampini }
6654