xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 5b7821680b9fd025da7be1a97316b179023235c8)
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__
81f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
91f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
101f4df5f7SStefano Zampini {
111f4df5f7SStefano Zampini   PetscErrorCode ierr;
121f4df5f7SStefano Zampini   Vec            local,global;
131f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
141f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
151f4df5f7SStefano Zampini 
161f4df5f7SStefano Zampini   PetscFunctionBegin;
171f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
181f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
191f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
201f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
211f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
221f4df5f7SStefano Zampini       PetscInt i;
231f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
241f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
251f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
261f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
271f4df5f7SStefano Zampini       }
281f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
291f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
301f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
311f4df5f7SStefano Zampini     }
321f4df5f7SStefano Zampini   } else {
33986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
341f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
35986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
36986cdee1SStefano Zampini       if (i > 1) {
37986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
381f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
391f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
401f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
411f4df5f7SStefano Zampini         }
421f4df5f7SStefano Zampini       }
431f4df5f7SStefano Zampini     }
44986cdee1SStefano Zampini   }
451f4df5f7SStefano Zampini 
461f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
471f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
481f4df5f7SStefano Zampini   }
491f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
501f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
511f4df5f7SStefano Zampini   }
521f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
531f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
541f4df5f7SStefano Zampini   }
551f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
561f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
571f4df5f7SStefano Zampini   PetscFunctionReturn(0);
581f4df5f7SStefano Zampini }
591f4df5f7SStefano Zampini 
601f4df5f7SStefano Zampini #undef __FUNCT__
613e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
623e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
633e589ea0SStefano Zampini {
643e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
653e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
663e589ea0SStefano Zampini   PetscErrorCode    ierr;
673e589ea0SStefano Zampini 
683e589ea0SStefano Zampini   PetscFunctionBegin;
693e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
703e589ea0SStefano Zampini     PetscFunctionReturn(0);
713e589ea0SStefano Zampini   }
723e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
733e589ea0SStefano Zampini     Vec swap;
743e589ea0SStefano Zampini 
753e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
763e589ea0SStefano Zampini     swap = pcbddc->work_change;
773e589ea0SStefano Zampini     pcbddc->work_change = r;
783e589ea0SStefano Zampini     r = swap;
793e589ea0SStefano Zampini   }
803e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
813e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
823e589ea0SStefano Zampini   if (pcbddc->benign_n) {
833e589ea0SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
843e589ea0SStefano Zampini   } else {
853e589ea0SStefano Zampini     ierr = VecSet(pcis->vec2_D,0.);CHKERRQ(ierr);
863e589ea0SStefano Zampini   }
873e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
883e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
893e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
903e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
913e589ea0SStefano Zampini     Vec swap;
923e589ea0SStefano Zampini 
933e589ea0SStefano Zampini     swap = r;
943e589ea0SStefano Zampini     r = pcbddc->work_change;
953e589ea0SStefano Zampini     pcbddc->work_change = swap;
963e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
973e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
983e589ea0SStefano Zampini   }
993e589ea0SStefano Zampini   PetscFunctionReturn(0);
1003e589ea0SStefano Zampini }
1013e589ea0SStefano Zampini 
1023e589ea0SStefano Zampini #undef __FUNCT__
103a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
104a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
105a3df083aSStefano Zampini {
106a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
107a3df083aSStefano Zampini   PetscErrorCode          ierr;
108a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
109a3df083aSStefano Zampini 
110a3df083aSStefano Zampini   PetscFunctionBegin;
111a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
112a3df083aSStefano Zampini   if (transpose) {
113a3df083aSStefano Zampini     apply_right = ctx->apply_left;
114a3df083aSStefano Zampini     apply_left = ctx->apply_right;
115a3df083aSStefano Zampini   } else {
116a3df083aSStefano Zampini     apply_right = ctx->apply_right;
117a3df083aSStefano Zampini     apply_left = ctx->apply_left;
118a3df083aSStefano Zampini   }
119a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
120a3df083aSStefano Zampini   if (apply_right) {
121a3df083aSStefano Zampini     const PetscScalar *ax;
122a3df083aSStefano Zampini     PetscInt          nl,i;
123a3df083aSStefano Zampini 
124a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
125a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
126a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
127a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
128a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
129a3df083aSStefano Zampini       PetscScalar    sum,val;
130a3df083aSStefano Zampini       const PetscInt *idxs;
131a3df083aSStefano Zampini       PetscInt       nz,j;
132a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
133a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
134a3df083aSStefano Zampini       sum = 0.;
135a3df083aSStefano Zampini       if (ctx->apply_p0) {
136a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
137a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
138a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
139a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
140a3df083aSStefano Zampini         }
141a3df083aSStefano Zampini       } else {
142a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
143a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
144a3df083aSStefano Zampini         }
145a3df083aSStefano Zampini       }
146a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
147a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
148a3df083aSStefano Zampini     }
149a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
150a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
151a3df083aSStefano Zampini   }
152a3df083aSStefano Zampini   if (transpose) {
153a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
154a3df083aSStefano Zampini   } else {
155a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
156a3df083aSStefano Zampini   }
157a3df083aSStefano Zampini   if (reset_x) {
158a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
159a3df083aSStefano Zampini   }
160a3df083aSStefano Zampini   if (apply_left) {
161a3df083aSStefano Zampini     PetscScalar *ay;
162a3df083aSStefano Zampini     PetscInt    i;
163a3df083aSStefano Zampini 
164a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
165a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
166a3df083aSStefano Zampini       PetscScalar    sum,val;
167a3df083aSStefano Zampini       const PetscInt *idxs;
168a3df083aSStefano Zampini       PetscInt       nz,j;
169a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
170a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
171a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
172a3df083aSStefano Zampini       if (ctx->apply_p0) {
173a3df083aSStefano Zampini         sum = 0.;
174a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
175a3df083aSStefano Zampini           sum += ay[idxs[j]];
176a3df083aSStefano Zampini           ay[idxs[j]] += val;
177a3df083aSStefano Zampini         }
178a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
179a3df083aSStefano Zampini       } else {
180a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
181a3df083aSStefano Zampini           ay[idxs[j]] += val;
182a3df083aSStefano Zampini         }
183a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
184a3df083aSStefano Zampini       }
185a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
186a3df083aSStefano Zampini     }
187a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
188a3df083aSStefano Zampini   }
189a3df083aSStefano Zampini   PetscFunctionReturn(0);
190a3df083aSStefano Zampini }
191a3df083aSStefano Zampini 
192a3df083aSStefano Zampini #undef __FUNCT__
193a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
194a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
195a3df083aSStefano Zampini {
196a3df083aSStefano Zampini   PetscErrorCode ierr;
197a3df083aSStefano Zampini 
198a3df083aSStefano Zampini   PetscFunctionBegin;
199a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
200a3df083aSStefano Zampini   PetscFunctionReturn(0);
201a3df083aSStefano Zampini }
202a3df083aSStefano Zampini 
203a3df083aSStefano Zampini #undef __FUNCT__
204a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
205a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
206a3df083aSStefano Zampini {
207a3df083aSStefano Zampini   PetscErrorCode ierr;
208a3df083aSStefano Zampini 
209a3df083aSStefano Zampini   PetscFunctionBegin;
210a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
211a3df083aSStefano Zampini   PetscFunctionReturn(0);
212a3df083aSStefano Zampini }
213a3df083aSStefano Zampini 
214a3df083aSStefano Zampini #undef __FUNCT__
215a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
216a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
217a3df083aSStefano Zampini {
218a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
219a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
220a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
221a3df083aSStefano Zampini   PetscErrorCode          ierr;
222a3df083aSStefano Zampini 
223a3df083aSStefano Zampini   PetscFunctionBegin;
224a3df083aSStefano Zampini   if (!restore) {
2251dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
226a3df083aSStefano Zampini     PetscScalar        *work;
227df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs->reuse_solver;
228a3df083aSStefano Zampini 
2291dd7afcfSStefano Zampini     if (pcbddc->benign_original_mat) {
2301dd7afcfSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
2311dd7afcfSStefano Zampini     }
2321dd7afcfSStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) {
2331dd7afcfSStefano Zampini       PetscFunctionReturn(0);
2341dd7afcfSStefano Zampini     }
235a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
236a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
237a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
238a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
239a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
240a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
241a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
242a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
243a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
244a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
245a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
246a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
247059032f7SStefano Zampini     if (reuse) {
248a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
2491dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
250059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
251059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
252059032f7SStefano Zampini       PetscInt               i;
253059032f7SStefano Zampini 
254059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
255059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
256059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
257059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
258059032f7SStefano Zampini       }
259059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
2601dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
261059032f7SStefano Zampini     }
262a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
263a3df083aSStefano Zampini     ctx->work = work;
264a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
265a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
266a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
267a3df083aSStefano Zampini     pcis->A_IB = A_IB;
268a3df083aSStefano Zampini 
269a3df083aSStefano Zampini     /* A_BI as A_IB^T */
270a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
271a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
272a3df083aSStefano Zampini     pcis->A_BI = A_BI;
273a3df083aSStefano Zampini   } else {
2741dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
2751dd7afcfSStefano Zampini       PetscFunctionReturn(0);
2761dd7afcfSStefano Zampini     }
277a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
278a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
279a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
2801dd7afcfSStefano Zampini     ctx->A = NULL;
2811dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
2821dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
2831dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
2841dd7afcfSStefano Zampini     if (ctx->free) {
285059032f7SStefano Zampini       PetscInt i;
2861dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
287059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
288059032f7SStefano Zampini       }
289059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
290059032f7SStefano Zampini     }
291a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
292a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
293a3df083aSStefano Zampini   }
294a3df083aSStefano Zampini   PetscFunctionReturn(0);
295a3df083aSStefano Zampini }
296a3df083aSStefano Zampini 
297a3df083aSStefano Zampini /* used just in bddc debug mode */
298a3df083aSStefano Zampini #undef __FUNCT__
299a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
300a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
301a3df083aSStefano Zampini {
302a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
303a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
304a3df083aSStefano Zampini   Mat            An;
305a3df083aSStefano Zampini   PetscErrorCode ierr;
306a3df083aSStefano Zampini 
307a3df083aSStefano Zampini   PetscFunctionBegin;
308a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
309a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
310a3df083aSStefano Zampini   if (is1) {
311a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
312a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
313a3df083aSStefano Zampini   } else {
314a3df083aSStefano Zampini     *B = An;
315a3df083aSStefano Zampini   }
316a3df083aSStefano Zampini   PetscFunctionReturn(0);
317a3df083aSStefano Zampini }
318a3df083aSStefano Zampini 
3191cf9b237SStefano Zampini /* TODO: add reuse flag */
3201cf9b237SStefano Zampini #undef __FUNCT__
3211cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
3221cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
3231cf9b237SStefano Zampini {
3241cf9b237SStefano Zampini   Mat            Bt;
3251cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
3261cf9b237SStefano Zampini   const PetscInt *ii,*ij;
3271cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
3281cf9b237SStefano Zampini   PetscBool      flg_row;
3291cf9b237SStefano Zampini   PetscErrorCode ierr;
3301cf9b237SStefano Zampini 
3311cf9b237SStefano Zampini   PetscFunctionBegin;
3321cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
3331cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
3341cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
3351cf9b237SStefano Zampini   nnz = n;
3361cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
3371cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
3381cf9b237SStefano Zampini   }
3391cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
3401cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
3411cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
3421cf9b237SStefano Zampini   nnz = 0;
3431cf9b237SStefano Zampini   bii[0] = 0;
3441cf9b237SStefano Zampini   for (i=0;i<n;i++) {
3451cf9b237SStefano Zampini     PetscInt j;
3461cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
3471cf9b237SStefano Zampini       PetscScalar entry = a[j];
3481cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
3491cf9b237SStefano Zampini         bij[nnz] = ij[j];
3501cf9b237SStefano Zampini         bdata[nnz] = entry;
3511cf9b237SStefano Zampini         nnz++;
3521cf9b237SStefano Zampini       }
3531cf9b237SStefano Zampini     }
3541cf9b237SStefano Zampini     bii[i+1] = nnz;
3551cf9b237SStefano Zampini   }
3561cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
3571cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
3581cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
3591cf9b237SStefano Zampini   {
3601cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
3611cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
3621cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
3631cf9b237SStefano Zampini   }
3641cf9b237SStefano Zampini   *B = Bt;
3651cf9b237SStefano Zampini   PetscFunctionReturn(0);
3661cf9b237SStefano Zampini }
3671cf9b237SStefano Zampini 
368674ae819SStefano Zampini #undef __FUNCT__
3694f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
3704f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
3714f1b2e48SStefano Zampini {
3724f1b2e48SStefano Zampini   Mat                    B;
3734f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
3744f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
3754f1b2e48SStefano Zampini   PCBDDCGraph            graph;
3764f1b2e48SStefano Zampini   PetscInt               i,n;
3774f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
3784f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
3794f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
3804f1b2e48SStefano Zampini   PetscErrorCode         ierr;
3814f1b2e48SStefano Zampini 
3824f1b2e48SStefano Zampini   PetscFunctionBegin;
38363c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
38463c961adSStefano Zampini     *ncc = 0;
38563c961adSStefano Zampini     *cc = NULL;
38663c961adSStefano Zampini     PetscFunctionReturn(0);
38763c961adSStefano Zampini   }
3884f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
3894f1b2e48SStefano Zampini   if (!isseqaij && filter) {
3901cf9b237SStefano Zampini     PetscBool isseqdense;
3911cf9b237SStefano Zampini 
3921cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
3931cf9b237SStefano Zampini     if (!isseqdense) {
3944f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
3951cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
3961cf9b237SStefano Zampini       PetscScalar *array;
3971cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
3981cf9b237SStefano Zampini 
3991cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
4001cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
4011cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
4021cf9b237SStefano Zampini       for (i=0;i<n;i++) {
4031cf9b237SStefano Zampini         PetscInt j;
4041cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
4051cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
4061cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
4071cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
4081cf9b237SStefano Zampini         }
4091cf9b237SStefano Zampini       }
4101cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
4119d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
4121cf9b237SStefano Zampini     }
4134f1b2e48SStefano Zampini   } else {
4144f1b2e48SStefano Zampini     B = A;
4154f1b2e48SStefano Zampini   }
4164f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4174f1b2e48SStefano Zampini 
4184f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
4194f1b2e48SStefano Zampini   if (filter) {
4204f1b2e48SStefano Zampini     PetscScalar *data;
4214f1b2e48SStefano Zampini     PetscInt    j,cum;
4224f1b2e48SStefano Zampini 
4234f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
4244f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
4254f1b2e48SStefano Zampini     cum = 0;
4264f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
4274f1b2e48SStefano Zampini       PetscInt t;
4284f1b2e48SStefano Zampini 
4294f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
4304f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
4314f1b2e48SStefano Zampini           continue;
4324f1b2e48SStefano Zampini         }
4334f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
4344f1b2e48SStefano Zampini       }
4354f1b2e48SStefano Zampini       t = xadj_filtered[i];
4364f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
4374f1b2e48SStefano Zampini       cum += t;
4384f1b2e48SStefano Zampini     }
4394f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
4404f1b2e48SStefano Zampini   } else {
4414f1b2e48SStefano Zampini     xadj_filtered = NULL;
4424f1b2e48SStefano Zampini     adjncy_filtered = NULL;
4434f1b2e48SStefano Zampini   }
4444f1b2e48SStefano Zampini 
4454f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
4464f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
4474f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
4484f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4494f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
4504f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
4514f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
4524f1b2e48SStefano Zampini   if (xadj_filtered) {
4534f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
4544f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
4554f1b2e48SStefano Zampini   } else {
4564f1b2e48SStefano Zampini     graph->xadj = xadj;
4574f1b2e48SStefano Zampini     graph->adjncy = adjncy;
4584f1b2e48SStefano Zampini   }
4594f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
4604f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4614f1b2e48SStefano Zampini   /* partial clean up */
4624f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
4634f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4641cf9b237SStefano Zampini   if (A != B) {
4654f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
4664f1b2e48SStefano Zampini   }
4674f1b2e48SStefano Zampini 
4684f1b2e48SStefano Zampini   /* get back data */
4691cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
4701cf9b237SStefano Zampini   if (cc) {
4714f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
4724f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
4734f1b2e48SStefano 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);
4744f1b2e48SStefano Zampini     }
4754f1b2e48SStefano Zampini     *cc = cc_n;
4761cf9b237SStefano Zampini   }
4774f1b2e48SStefano Zampini   /* clean up graph */
4784f1b2e48SStefano Zampini   graph->xadj = 0;
4794f1b2e48SStefano Zampini   graph->adjncy = 0;
4804f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
4814f1b2e48SStefano Zampini   PetscFunctionReturn(0);
4824f1b2e48SStefano Zampini }
4834f1b2e48SStefano Zampini 
4844f1b2e48SStefano Zampini #undef __FUNCT__
4855408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
4865408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
4875408967cSStefano Zampini {
4885408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4895408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
490dee84bffSStefano Zampini   IS             dirIS = NULL;
4914f1b2e48SStefano Zampini   PetscInt       i;
4925408967cSStefano Zampini   PetscErrorCode ierr;
4935408967cSStefano Zampini 
4945408967cSStefano Zampini   PetscFunctionBegin;
495dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
4965408967cSStefano Zampini   if (zerodiag) {
4975408967cSStefano Zampini     Mat            A;
4985408967cSStefano Zampini     Vec            vec3_N;
4995408967cSStefano Zampini     PetscScalar    *vals;
5005408967cSStefano Zampini     const PetscInt *idxs;
501d12d3064SStefano Zampini     PetscInt       nz,*count;
5025408967cSStefano Zampini 
5035408967cSStefano Zampini     /* p0 */
5045408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
5055408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
5065408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5075408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
5084f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
5095408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5105408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5115408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5125408967cSStefano Zampini     /* v_I */
5135408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
5145408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
5155408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5165408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
5175408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
5185408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
5195408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5205408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
5215408967cSStefano Zampini     if (dirIS) {
5225408967cSStefano Zampini       PetscInt n;
5235408967cSStefano Zampini 
5245408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
5255408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
5265408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
5275408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5285408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
5295408967cSStefano Zampini     }
5305408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
5315408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
5325408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
5335408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
5345408967cSStefano Zampini     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
5355408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
5365408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
537fbfcb133SStefano Zampini     if (PetscAbsScalar(vals[0]) > 1.e-1) {
538b9b0e38cSStefano 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]));
5395408967cSStefano Zampini     }
5405408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
5415408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
542d12d3064SStefano Zampini 
543d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
544d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
545d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
546d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
547d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
548d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
549d4d8cf7bSStefano Zampini     for (i=0;i<nz;i++) {
550d12d3064SStefano Zampini       if (count[idxs[i]]) {
551d12d3064SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
552d12d3064SStefano Zampini       }
553d4d8cf7bSStefano Zampini     }
554d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
555d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
5565408967cSStefano Zampini   }
557dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
5585408967cSStefano Zampini 
5595408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
5605408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
5614f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
5625408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
5634f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
5645408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
5654f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
5664f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
5674f1b2e48SStefano 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);
5684f1b2e48SStefano Zampini     }
5695408967cSStefano Zampini   }
5705408967cSStefano Zampini   PetscFunctionReturn(0);
5715408967cSStefano Zampini }
5725408967cSStefano Zampini 
5735408967cSStefano Zampini #undef __FUNCT__
574339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
575339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
576339f8db1SStefano Zampini {
577339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5784f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
579b0f5fe93SStefano Zampini   PetscInt       nz,n;
5801f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
5814f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
582339f8db1SStefano Zampini   PetscErrorCode ierr;
583339f8db1SStefano Zampini 
584339f8db1SStefano Zampini   PetscFunctionBegin;
5859f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
5869f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
587a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
588a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
589a3df083aSStefano Zampini   }
590a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
591a3df083aSStefano Zampini   pcbddc->benign_n = 0;
5924f1b2e48SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
5934f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
5944f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
5954f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
5964f1b2e48SStefano Zampini      since the local Schur complements are SPD
5974f1b2e48SStefano Zampini   */
5984f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
5994f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
60040fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
6014f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
6024f1b2e48SStefano Zampini 
6034f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
6044f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
6054f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
6064f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
607ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
60840fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
60940fa8d13SStefano Zampini     if (!sorted) {
61040fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
61140fa8d13SStefano Zampini     }
61240fa8d13SStefano Zampini   } else {
61340fa8d13SStefano Zampini     pressures = NULL;
61440fa8d13SStefano Zampini   }
61597d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
61697d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
61727b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
61897d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
619339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
620339f8db1SStefano Zampini   if (!sorted) {
621339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
622339f8db1SStefano Zampini   }
623339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
6244f1b2e48SStefano Zampini   if (!nz) {
6254f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
6264f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
62740fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
62840fa8d13SStefano Zampini   }
6294f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
6304f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
6314f1b2e48SStefano Zampini   zerodiag_subs = NULL;
6324f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
6331f4df5f7SStefano Zampini   n_interior_dofs = 0;
6341f4df5f7SStefano Zampini   interior_dofs = NULL;
6351f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
6361f4df5f7SStefano Zampini     PetscInt n,i,j;
6371f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
6381f4df5f7SStefano Zampini     PetscInt *iwork;
6391f4df5f7SStefano Zampini 
6401f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
6411f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6421f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
6431f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
6441f4df5f7SStefano Zampini     for (i=0;i<n_neigh;i++)
6451f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
6461f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
6471f4df5f7SStefano Zampini     for (i=0;i<n;i++)
6481f4df5f7SStefano Zampini       if (!iwork[i])
6491f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
6501f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
6511f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6521f4df5f7SStefano Zampini   }
6534f1b2e48SStefano Zampini   if (has_null_pressures) {
6544f1b2e48SStefano Zampini     IS             *subs;
6551f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
6561f4df5f7SStefano Zampini     const PetscInt *idxs;
6571f4df5f7SStefano Zampini     PetscScalar    *array;
6581f4df5f7SStefano Zampini     Vec            *work;
6591f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
6604f1b2e48SStefano Zampini 
6614f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
6624f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
6631f4df5f7SStefano 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) */
6641f4df5f7SStefano Zampini     if (pcbddc->current_level) {
6651f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
6661f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
6671f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
6681f4df5f7SStefano Zampini       /* work[0] = 1_p */
6691f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
6701f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
6711f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
6721f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
6731f4df5f7SStefano Zampini       /* work[0] = 1_v */
6741f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
6751f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
6761f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
6771f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
6781f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
6791f4df5f7SStefano Zampini     }
6804f1b2e48SStefano Zampini     if (nsubs > 1) {
6814f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
6824f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
6834f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
6844f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
6854f1b2e48SStefano Zampini         PetscInt               nl;
6864f1b2e48SStefano Zampini 
6874f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
6884f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
6894f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
6904f1b2e48SStefano Zampini         if (nl) {
6914f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
6924f1b2e48SStefano Zampini 
6931f4df5f7SStefano Zampini           if (pcbddc->current_level) {
6941f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
6951f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
6961f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
6971f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
6981f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
6991f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
7001f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
7011f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
7021f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
7031f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
7041f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
7051f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
7061f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
7071f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
7081f4df5f7SStefano Zampini                 break;
7091f4df5f7SStefano Zampini               }
7101f4df5f7SStefano Zampini             }
7111f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
7121f4df5f7SStefano Zampini           }
7131f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
7141f4df5f7SStefano Zampini             IS       t_bc;
7151f4df5f7SStefano Zampini             PetscInt nzb;
7161f4df5f7SStefano Zampini 
7171f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
7181f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
7191f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
7201f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
7211f4df5f7SStefano Zampini           }
7221f4df5f7SStefano Zampini           if (valid && pressures) {
7234f1b2e48SStefano Zampini             IS t_pressure_subs;
7244f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
7254f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
7264f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
7274f1b2e48SStefano Zampini           }
7284f1b2e48SStefano Zampini           if (valid) {
7294f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
7304f1b2e48SStefano Zampini             pcbddc->benign_n++;
7314f1b2e48SStefano Zampini           } else {
7324f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
7334f1b2e48SStefano Zampini           }
7344f1b2e48SStefano Zampini         }
7354f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
7364f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
7374f1b2e48SStefano Zampini       }
7384f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
7394f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
7401f4df5f7SStefano Zampini 
7411f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
7421f4df5f7SStefano Zampini         PetscInt nzb;
7431f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
7441f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
7451f4df5f7SStefano Zampini       }
7461f4df5f7SStefano Zampini       if (valid && pressures) {
7474f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
7484f1b2e48SStefano Zampini       }
7491f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
7501f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
7511f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
7521f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
7531f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
7541f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
7551f4df5f7SStefano Zampini               valid = PETSC_FALSE;
7561f4df5f7SStefano Zampini               break;
7571f4df5f7SStefano Zampini           }
7581f4df5f7SStefano Zampini         }
7591f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
7601f4df5f7SStefano Zampini       }
7614f1b2e48SStefano Zampini       if (valid) {
7624f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
763ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
7644f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
7654f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
7664f1b2e48SStefano Zampini       }
7674f1b2e48SStefano Zampini     }
7681f4df5f7SStefano Zampini     if (pcbddc->current_level) {
7691f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
7704f1b2e48SStefano Zampini     }
7711f4df5f7SStefano Zampini   }
7721f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
7734f1b2e48SStefano Zampini 
7744f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
775b9b0e38cSStefano Zampini     PetscInt n;
776b9b0e38cSStefano Zampini 
7774f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
7784f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
779b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
780b9b0e38cSStefano Zampini     if (n) {
7814f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
7824f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
7834f1b2e48SStefano Zampini     }
784b9b0e38cSStefano Zampini   }
7854f1b2e48SStefano Zampini 
7864f1b2e48SStefano Zampini   /* final check for null pressures */
7874f1b2e48SStefano Zampini   if (zerodiag && pressures) {
7884f1b2e48SStefano Zampini     PetscInt nz,np;
7894f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
7904f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
7914f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
7924f1b2e48SStefano Zampini   }
7934f1b2e48SStefano Zampini 
7944f1b2e48SStefano Zampini   if (recompute_zerodiag) {
7954f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
7964f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
7974f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
7984f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
7994f1b2e48SStefano Zampini     } else {
8004f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
8014f1b2e48SStefano Zampini 
8024f1b2e48SStefano Zampini       nzn = 0;
8034f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
8044f1b2e48SStefano Zampini         PetscInt ns;
8054f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
8064f1b2e48SStefano Zampini         nzn += ns;
8074f1b2e48SStefano Zampini       }
8084f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
8094f1b2e48SStefano Zampini       nzn = 0;
8104f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
8114f1b2e48SStefano Zampini         PetscInt ns,*idxs;
8124f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
8134f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
8144f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
8154f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
8164f1b2e48SStefano Zampini         nzn += ns;
8174f1b2e48SStefano Zampini       }
8184f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
8194f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
8204f1b2e48SStefano Zampini     }
8214f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
8224f1b2e48SStefano Zampini   }
8234f1b2e48SStefano Zampini 
824b3afcdbeSStefano Zampini   /* no-net-flux */
825b3afcdbeSStefano Zampini   if (pcbddc->benign_compute_nonetflux) {
826b3afcdbeSStefano Zampini     Mat_IS*                matis = (Mat_IS*)(pc->pmat->data);
827b3afcdbeSStefano Zampini     MatNullSpace           near_null_space;
828b3afcdbeSStefano Zampini     ISLocalToGlobalMapping rmap;
829b3afcdbeSStefano Zampini     Vec                    quad_vec;
830b3afcdbeSStefano Zampini     PetscScalar            *pvals;
831b3afcdbeSStefano Zampini     PetscInt               i,np,*dummyins;
8321f4df5f7SStefano Zampini     IS                     isused = NULL;
8331f4df5f7SStefano Zampini     PetscBool              participate = PETSC_TRUE;
834b3afcdbeSStefano Zampini 
835b3afcdbeSStefano Zampini     /* create vector to hold quadrature weights */
836b3afcdbeSStefano Zampini     ierr = MatCreateVecs(pc->pmat,&quad_vec,NULL);CHKERRQ(ierr);
837b3afcdbeSStefano Zampini     ierr = VecSet(quad_vec,0.0);CHKERRQ(ierr);
838b3afcdbeSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&rmap,NULL);CHKERRQ(ierr);
839b3afcdbeSStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vec,rmap);CHKERRQ(ierr);
840b3afcdbeSStefano Zampini 
841b3afcdbeSStefano Zampini     /* compute B^{(i)T} * 1_p */
842b3afcdbeSStefano Zampini     np = 0;
8431f4df5f7SStefano Zampini     if (pressures) {
8441f4df5f7SStefano Zampini       isused = pressures;
8451f4df5f7SStefano Zampini     } else {
8461f4df5f7SStefano Zampini       isused = zerodiag;
8471f4df5f7SStefano Zampini     }
8481f4df5f7SStefano Zampini     if (isused) {
8491f4df5f7SStefano Zampini       ierr = ISGetLocalSize(isused,&np);CHKERRQ(ierr);
850b3afcdbeSStefano Zampini     }
851b3afcdbeSStefano Zampini     ierr = PetscMalloc1(np,&pvals);CHKERRQ(ierr);
852b3afcdbeSStefano Zampini     for (i=0;i<np;i++) pvals[i] = 1.;
853b3afcdbeSStefano Zampini     ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
854b3afcdbeSStefano Zampini     if (np) {
855b3afcdbeSStefano Zampini       const PetscInt *pidxs;
856b3afcdbeSStefano Zampini 
8571f4df5f7SStefano Zampini       if (isused) {
8581f4df5f7SStefano Zampini         ierr = ISGetIndices(isused,&pidxs);CHKERRQ(ierr);
859b3afcdbeSStefano Zampini       }
860b3afcdbeSStefano Zampini       ierr = VecSetValues(matis->x,np,pidxs,pvals,INSERT_VALUES);CHKERRQ(ierr);
8611f4df5f7SStefano Zampini       if (isused) {
8621f4df5f7SStefano Zampini         ierr = ISRestoreIndices(isused,&pidxs);CHKERRQ(ierr);
863b3afcdbeSStefano Zampini       }
864b3afcdbeSStefano Zampini     }
865b3afcdbeSStefano Zampini     ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
866b3afcdbeSStefano Zampini     ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
867b3afcdbeSStefano Zampini     ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
868b3afcdbeSStefano Zampini     ierr = PetscFree(pvals);CHKERRQ(ierr);
8691f4df5f7SStefano Zampini     if (!isused) participate = PETSC_FALSE;
870b3afcdbeSStefano Zampini     /* decide which of the sharing ranks (per dof) has to insert the values (should just be a matter of having a different orientation) */
871b3afcdbeSStefano Zampini     ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
872daf8a457SStefano Zampini     for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = -1;
8731f4df5f7SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++)
8741f4df5f7SStefano Zampini       if (participate) matis->sf_leafdata[i] = PetscGlobalRank;
8751f4df5f7SStefano Zampini       else  matis->sf_leafdata[i] = -1;
8761f4df5f7SStefano Zampini 
877b3afcdbeSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_MAX);CHKERRQ(ierr);
878b3afcdbeSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_MAX);CHKERRQ(ierr);
879b3afcdbeSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
880b3afcdbeSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
881b3afcdbeSStefano Zampini     ierr = VecGetArray(matis->y,&pvals);CHKERRQ(ierr);
882daf8a457SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++) {
883b3afcdbeSStefano Zampini       if (PetscGlobalRank != matis->sf_leafdata[i]) {
884b3afcdbeSStefano Zampini         pvals[i] = 0.;
885b3afcdbeSStefano Zampini       }
886b3afcdbeSStefano Zampini     }
887daf8a457SStefano Zampini     ierr = PetscMalloc1(matis->sf->nleaves,&dummyins);CHKERRQ(ierr);
888daf8a457SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++) dummyins[i] = i;
889daf8a457SStefano Zampini     ierr = VecSetValuesLocal(quad_vec,matis->sf->nleaves,dummyins,pvals,ADD_VALUES);CHKERRQ(ierr);
890b3afcdbeSStefano Zampini     ierr = VecRestoreArray(matis->y,&pvals);CHKERRQ(ierr);
891b3afcdbeSStefano Zampini     ierr = PetscFree(dummyins);CHKERRQ(ierr);
892b3afcdbeSStefano Zampini 
893b3afcdbeSStefano Zampini     /* assembly quadrature vec and attach near null space to pmat */
894b3afcdbeSStefano Zampini     ierr = VecAssemblyBegin(quad_vec);CHKERRQ(ierr);
895b3afcdbeSStefano Zampini     ierr = VecAssemblyEnd(quad_vec);CHKERRQ(ierr);
896b3afcdbeSStefano Zampini     ierr = VecNormalize(quad_vec,NULL);CHKERRQ(ierr);
897b3afcdbeSStefano Zampini     ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,1,&quad_vec,&near_null_space);CHKERRQ(ierr);
898b3afcdbeSStefano Zampini     ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
899b3afcdbeSStefano Zampini     ierr = MatSetNearNullSpace(pc->pmat,near_null_space);CHKERRQ(ierr);
900b3afcdbeSStefano Zampini     ierr = MatNullSpaceDestroy(&near_null_space);CHKERRQ(ierr);
901b3afcdbeSStefano Zampini   }
902b3afcdbeSStefano Zampini 
903b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
9044f1b2e48SStefano Zampini   if (has_null_pressures) {
9054f1b2e48SStefano Zampini     IS             zerodiagc;
9064f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
9074f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
9084f1b2e48SStefano Zampini 
9094f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
910339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
911339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
912339f8db1SStefano Zampini     /* local change of basis for pressures */
913339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
91497d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
915339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
916339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
917339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
9184f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
9194f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
9204f1b2e48SStefano Zampini       PetscInt nzs,j;
9214f1b2e48SStefano Zampini 
9224f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
9234f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
9244f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
9254f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
9264f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
9274f1b2e48SStefano Zampini     }
928339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
929339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
930339f8db1SStefano Zampini     /* set identity on velocities */
931339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
932339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
933339f8db1SStefano Zampini     }
9344f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
9354f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
9369f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
9374f1b2e48SStefano 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);
938339f8db1SStefano Zampini     /* set change on pressures */
9394f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
9404f1b2e48SStefano Zampini       PetscScalar *array;
9414f1b2e48SStefano Zampini       PetscInt    nzs;
9424f1b2e48SStefano Zampini 
9434f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
9444f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
9454f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
946339f8db1SStefano Zampini         PetscScalar vals[2];
947339f8db1SStefano Zampini         PetscInt    cols[2];
948339f8db1SStefano Zampini 
949339f8db1SStefano Zampini         cols[0] = idxs[i];
9504f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
951339f8db1SStefano Zampini         vals[0] = 1.;
952b0f5fe93SStefano Zampini         vals[1] = 1.;
9534f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
954339f8db1SStefano Zampini       }
9554f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
9564f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
9574f1b2e48SStefano Zampini       array[nzs-1] = 1.;
9584f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
9594f1b2e48SStefano Zampini       /* store local idxs for p0 */
9604f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
9614f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
962339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
9634f1b2e48SStefano Zampini     }
964339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
965339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
966a3df083aSStefano Zampini     /* project if needed */
967a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
9681dd7afcfSStefano Zampini       Mat M;
9691dd7afcfSStefano Zampini 
9701dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
971339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
9721dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
9731dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
974a3df083aSStefano Zampini     }
9754f1b2e48SStefano Zampini     /* store global idxs for p0 */
9764f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
977339f8db1SStefano Zampini   }
978ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
9794f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
980b0f5fe93SStefano Zampini 
981b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
982b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
98327b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
98427b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
985339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
986339f8db1SStefano Zampini   PetscFunctionReturn(0);
987339f8db1SStefano Zampini }
988339f8db1SStefano Zampini 
989339f8db1SStefano Zampini #undef __FUNCT__
990015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
991015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
992efc2fbd9SStefano Zampini {
993efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
994de9d7bd0SStefano Zampini   PetscScalar    *array;
995efc2fbd9SStefano Zampini   PetscErrorCode ierr;
996efc2fbd9SStefano Zampini 
997efc2fbd9SStefano Zampini   PetscFunctionBegin;
998efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
999efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
10004f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1001efc2fbd9SStefano Zampini   }
1002de9d7bd0SStefano Zampini   if (get) {
1003efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
10044f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
10054f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
1006efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
1007de9d7bd0SStefano Zampini   } else {
1008de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
1009de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1010de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1011de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
1012efc2fbd9SStefano Zampini   }
1013efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
1014efc2fbd9SStefano Zampini }
1015efc2fbd9SStefano Zampini 
1016efc2fbd9SStefano Zampini #undef __FUNCT__
1017c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
1018c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
1019c263805aSStefano Zampini {
1020c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1021c263805aSStefano Zampini   PetscErrorCode ierr;
1022c263805aSStefano Zampini 
1023c263805aSStefano Zampini   PetscFunctionBegin;
1024c263805aSStefano Zampini   /* TODO: add error checking
1025c263805aSStefano Zampini     - avoid nested pop (or push) calls.
1026c263805aSStefano Zampini     - cannot push before pop.
10271c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
1028c263805aSStefano Zampini   */
10294f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1030efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
1031efc2fbd9SStefano Zampini   }
1032c263805aSStefano Zampini   if (pop) {
1033a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
10344f1b2e48SStefano Zampini       IS       is_p0;
10354f1b2e48SStefano Zampini       MatReuse reuse;
1036c263805aSStefano Zampini 
1037c263805aSStefano Zampini       /* extract B_0 */
10384f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
10394f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
10404f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
10414f1b2e48SStefano Zampini       }
10424f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
10434f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
1044c263805aSStefano Zampini       /* remove rows and cols from local problem */
1045c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
104697d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
10474f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
10484f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
1049a3df083aSStefano Zampini     } else {
1050a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
1051a3df083aSStefano Zampini       PetscScalar *vals;
1052a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
1053a3df083aSStefano Zampini 
1054a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
1055a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
1056a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
10570b5adadeSStefano Zampini         PetscInt *nnz;
1058a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
1059a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
1060a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1061331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
1062331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
1063331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
1064331e053bSStefano Zampini           nnz[i] = n - nnz[i];
1065331e053bSStefano Zampini         }
1066331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
1067331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
1068331e053bSStefano Zampini       }
1069a3df083aSStefano Zampini 
1070a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1071a3df083aSStefano Zampini         PetscScalar *array;
1072a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
1073a3df083aSStefano Zampini 
1074a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
1075a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1076a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1077a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
1078a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1079a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
1080a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
1081a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
1082a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
1083a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
1084a3df083aSStefano Zampini         cum = 0;
1085a3df083aSStefano Zampini         for (j=0;j<n;j++) {
108622db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
1087a3df083aSStefano Zampini             vals[cum] = array[j];
1088a3df083aSStefano Zampini             idxs_ins[cum] = j;
1089a3df083aSStefano Zampini             cum++;
1090a3df083aSStefano Zampini           }
1091a3df083aSStefano Zampini         }
1092a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
1093a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
1094a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1095a3df083aSStefano Zampini       }
1096a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1097a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1098a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
1099a3df083aSStefano Zampini     }
1100c263805aSStefano Zampini   } else { /* push */
1101a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
11024f1b2e48SStefano Zampini       PetscInt i;
11034f1b2e48SStefano Zampini 
11044f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
11054f1b2e48SStefano Zampini         PetscScalar *B0_vals;
11064f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
11074f1b2e48SStefano Zampini 
11084f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
11094f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
11107b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
11114f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
11124f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
11134f1b2e48SStefano Zampini       }
1114c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1115c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1116a3df083aSStefano Zampini     } else {
1117a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
1118a3df083aSStefano Zampini     }
1119c263805aSStefano Zampini   }
1120c263805aSStefano Zampini   PetscFunctionReturn(0);
1121c263805aSStefano Zampini }
1122c263805aSStefano Zampini 
1123c263805aSStefano Zampini #undef __FUNCT__
1124b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
112508122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
1126b1b3d7a2SStefano Zampini {
1127b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
112808122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
112908122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
113008122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
113108122e43SStefano Zampini   PetscScalar     *work,lwork;
113208122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
113308122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
113408122e43SStefano Zampini   PetscReal       *eigs,thresh;
11351b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
1136f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
113708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
113808122e43SStefano Zampini   PetscReal       *rwork;
113908122e43SStefano Zampini #endif
1140b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
1141b1b3d7a2SStefano Zampini 
1142b1b3d7a2SStefano Zampini   PetscFunctionBegin;
1143af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
1144af25d912SStefano 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);
114506a4e24aSStefano Zampini 
1146fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1147fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1148fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1149fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
11501575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1151fd14bc51SStefano Zampini   }
1152fd14bc51SStefano Zampini 
1153e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
1154e496cd5dSStefano 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);
1155e496cd5dSStefano Zampini   }
1156e496cd5dSStefano Zampini 
115708122e43SStefano Zampini   /* max size of subsets */
115808122e43SStefano Zampini   mss = 0;
115908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
116008122e43SStefano Zampini     PetscInt subset_size;
1161862806e4SStefano Zampini 
116208122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
116308122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
116408122e43SStefano Zampini   }
116508122e43SStefano Zampini 
116608122e43SStefano Zampini   /* min/max and threshold */
116708122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
1168f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
116908122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
1170f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
1171f6f667cfSStefano Zampini   if (nmin) {
1172f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
1173f6f667cfSStefano Zampini   }
117408122e43SStefano Zampini 
117508122e43SStefano Zampini   /* allocate lapack workspace */
117608122e43SStefano Zampini   cum = cum2 = 0;
117708122e43SStefano Zampini   maxneigs = 0;
117808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
117908122e43SStefano Zampini     PetscInt n,subset_size;
1180f6f667cfSStefano Zampini 
118108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
118208122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
11839162d606SStefano Zampini     cum += subset_size;
11849162d606SStefano Zampini     cum2 += subset_size*n;
118508122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
118608122e43SStefano Zampini   }
118708122e43SStefano Zampini   if (mss) {
11889ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
118908122e43SStefano Zampini       PetscBLASInt B_itype = 1;
119008122e43SStefano Zampini       PetscBLASInt B_N = mss;
11914c6709b3SStefano Zampini       PetscReal    zero = 0.0;
11924c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
119308122e43SStefano Zampini 
119408122e43SStefano Zampini       B_lwork = -1;
119508122e43SStefano Zampini       S = NULL;
119608122e43SStefano Zampini       St = NULL;
1197a58a30b4SStefano Zampini       eigs = NULL;
1198a58a30b4SStefano Zampini       eigv = NULL;
1199a58a30b4SStefano Zampini       B_iwork = NULL;
1200a58a30b4SStefano Zampini       B_ifail = NULL;
1201d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1202d1710679SStefano Zampini       rwork = NULL;
1203d1710679SStefano Zampini #endif
12048bec7fa6SStefano Zampini       thresh = 1.0;
120508122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
120608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
120708122e43SStefano 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));
120808122e43SStefano Zampini #else
120908122e43SStefano 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));
121008122e43SStefano Zampini #endif
121108122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
121208122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
121308122e43SStefano Zampini     } else {
121408122e43SStefano Zampini         /* TODO */
121508122e43SStefano Zampini     }
121608122e43SStefano Zampini   } else {
121708122e43SStefano Zampini     lwork = 0;
121808122e43SStefano Zampini   }
121908122e43SStefano Zampini 
122008122e43SStefano Zampini   nv = 0;
1221d62866d3SStefano 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) */
1222d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
122308122e43SStefano Zampini   }
12244c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
1225f6f667cfSStefano Zampini   if (allocated_S_St) {
1226f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
1227f6f667cfSStefano Zampini   }
1228f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
122908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
123008122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
123108122e43SStefano Zampini #endif
12329162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
12339162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
12349162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
123508122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
12369162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
123708122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
123808122e43SStefano Zampini 
123908122e43SStefano Zampini   maxneigs = 0;
124072b8c272SStefano Zampini   cum = cumarray = 0;
12419162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
12429162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
1243d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
124408122e43SStefano Zampini     const PetscInt *idxs;
124508122e43SStefano Zampini 
1246d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
124708122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
124808122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
124908122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
125008122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
12519162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
12529162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
125308122e43SStefano Zampini     }
1254d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
125508122e43SStefano Zampini   }
125608122e43SStefano Zampini 
125708122e43SStefano Zampini   if (mss) { /* multilevel */
125808122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
125908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
126008122e43SStefano Zampini   }
126108122e43SStefano Zampini 
1262ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
126308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
126408122e43SStefano Zampini     const PetscInt *idxs;
12659d54b7f4SStefano Zampini     PetscReal      upper,lower;
1266862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
126708122e43SStefano Zampini     PetscBLASInt   B_N;
1268aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
126908122e43SStefano Zampini 
12709d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
12719d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
12729d54b7f4SStefano Zampini       lower = thresh;
12739d54b7f4SStefano Zampini     } else {
12749d54b7f4SStefano Zampini       upper = 1./thresh;
12759d54b7f4SStefano Zampini       lower = 0.;
12769d54b7f4SStefano Zampini     }
1277862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
1278ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
1279f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
1280f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
12819ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
1282aff50787SStefano Zampini         PetscInt j,k;
1283aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
1284aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1285aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
128608122e43SStefano Zampini         }
128708122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1288aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1289aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1290aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1291aff50787SStefano Zampini           }
129208122e43SStefano Zampini         }
129308122e43SStefano Zampini       } else {
129408122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
129508122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
129608122e43SStefano Zampini       }
12978bec7fa6SStefano Zampini     } else {
1298f6f667cfSStefano Zampini       S = Sarray + cumarray;
1299f6f667cfSStefano Zampini       St = Starray + cumarray;
13008bec7fa6SStefano Zampini     }
1301aff50787SStefano Zampini     /* see if we can save some work */
1302b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
1303aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1304aff50787SStefano Zampini     }
1305aff50787SStefano Zampini 
1306b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
1307aff50787SStefano Zampini       B_neigs = 0;
1308aff50787SStefano Zampini     } else {
13099ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
131008122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1311f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
13124c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
13139552c7c7SStefano Zampini         PetscInt     nmin_s;
1314b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
131508122e43SStefano Zampini 
1316fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
13178bec7fa6SStefano 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]]);
1318fd14bc51SStefano Zampini         }
1319d16cbb6bSStefano Zampini 
1320b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
1321b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
1322b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
1323b7ab4a40SStefano Zampini         }
1324b7ab4a40SStefano Zampini 
132508122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1326b7ab4a40SStefano Zampini         if (compute_range) {
1327d16cbb6bSStefano Zampini 
1328d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
132908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
13309d54b7f4SStefano 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));
133108122e43SStefano Zampini #else
13329d54b7f4SStefano 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));
133308122e43SStefano Zampini #endif
1334b7ab4a40SStefano Zampini         } else if (!same_data) {
1335d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1336d16cbb6bSStefano Zampini           B_IL = 1;
1337d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
13389d54b7f4SStefano 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));
1339d16cbb6bSStefano Zampini #else
13409d54b7f4SStefano 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));
1341d16cbb6bSStefano Zampini #endif
1342b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
1343b7ab4a40SStefano Zampini           PetscInt k;
1344b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
1345b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
1346b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
1347b7ab4a40SStefano Zampini           nmin = nmax;
1348b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1349b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
1350b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
1351b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
1352b7ab4a40SStefano Zampini           }
1353d16cbb6bSStefano Zampini         }
135408122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
135508122e43SStefano Zampini         if (B_ierr) {
13566c4ed002SBarry 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);
13576c4ed002SBarry 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);
13586c4ed002SBarry 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);
135908122e43SStefano Zampini         }
136008122e43SStefano Zampini 
136108122e43SStefano Zampini         if (B_neigs > nmax) {
1362fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1363fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1364fd14bc51SStefano Zampini           }
13659d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
136608122e43SStefano Zampini           B_neigs = nmax;
136708122e43SStefano Zampini         }
136808122e43SStefano Zampini 
13699552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
13709552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
137108122e43SStefano Zampini           PetscBLASInt B_neigs2;
137208122e43SStefano Zampini 
13739d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
1374f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
13759d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
13769d54b7f4SStefano Zampini           } else {
13779d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
13789d54b7f4SStefano Zampini             B_IU = nmin_s;
13799d54b7f4SStefano Zampini           }
1380fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1381fd14bc51SStefano 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);
1382fd14bc51SStefano Zampini           }
13839ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
138408122e43SStefano Zampini             PetscInt j;
138508122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
138608122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
138708122e43SStefano Zampini             }
138808122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
138908122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
139008122e43SStefano Zampini             }
139108122e43SStefano Zampini           } else {
139208122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139308122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139408122e43SStefano Zampini           }
139508122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
139608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
13979d54b7f4SStefano 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));
139808122e43SStefano Zampini #else
13999d54b7f4SStefano 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));
140008122e43SStefano Zampini #endif
140108122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
140208122e43SStefano Zampini           B_neigs += B_neigs2;
140308122e43SStefano Zampini         }
140408122e43SStefano Zampini         if (B_ierr) {
14056c4ed002SBarry 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);
14066c4ed002SBarry 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);
14076c4ed002SBarry 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);
140808122e43SStefano Zampini         }
1409fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1410ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
141108122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
141208122e43SStefano Zampini             if (eigs[j] == 0.0) {
1413ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
141408122e43SStefano Zampini             } else {
14159d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
1416ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
14179d54b7f4SStefano Zampini               } else {
14189d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
14199d54b7f4SStefano Zampini               }
1420fd14bc51SStefano Zampini             }
142108122e43SStefano Zampini           }
142208122e43SStefano Zampini         }
142308122e43SStefano Zampini       } else {
142408122e43SStefano Zampini           /* TODO */
142508122e43SStefano Zampini       }
1426aff50787SStefano Zampini     }
14276c3e6151SStefano Zampini     /* change the basis back to the original one */
14286c3e6151SStefano Zampini     if (sub_schurs->change) {
142972b8c272SStefano Zampini       Mat change,phi,phit;
14306c3e6151SStefano Zampini 
14316c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
14326c3e6151SStefano Zampini         PetscInt ii;
14336c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
14346c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
14356c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
14366c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
14376c3e6151SStefano Zampini           }
14386c3e6151SStefano Zampini         }
14396c3e6151SStefano Zampini       }
144072b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
14416c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
144272b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
14436c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
14446c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
14456c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
14466c3e6151SStefano Zampini     }
14478bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
14488bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
14499162d606SStefano Zampini     if (B_neigs) {
14509162d606SStefano 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);
1451fd14bc51SStefano Zampini 
1452fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
14539552c7c7SStefano Zampini         PetscInt ii;
14549552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1455ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
14569552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1457ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1458ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1459ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1460ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1461ac47001eSStefano Zampini #else
1462ac47001eSStefano 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);
1463ac47001eSStefano Zampini #endif
14649552c7c7SStefano Zampini           }
14659552c7c7SStefano Zampini         }
1466fd14bc51SStefano Zampini       }
14679162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
14689162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
14699162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
14709162d606SStefano Zampini       cum++;
147108122e43SStefano Zampini     }
147208122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
147308122e43SStefano Zampini     /* shift for next computation */
147408122e43SStefano Zampini     cumarray += subset_size*subset_size;
147508122e43SStefano Zampini   }
1476fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1477fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1478fd14bc51SStefano Zampini   }
147908122e43SStefano Zampini 
148008122e43SStefano Zampini   if (mss) {
148108122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
148208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1483f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1484f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1485f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
148608122e43SStefano Zampini   }
1487f6f667cfSStefano Zampini   if (allocated_S_St) {
1488f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1489f6f667cfSStefano Zampini   }
1490f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
149108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
149208122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
149308122e43SStefano Zampini #endif
149408122e43SStefano Zampini   if (pcbddc->dbg_flag) {
14951b968477SStefano Zampini     PetscInt maxneigs_r;
1496b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
14979b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
149808122e43SStefano Zampini   }
149908122e43SStefano Zampini   PetscFunctionReturn(0);
150008122e43SStefano Zampini }
1501b1b3d7a2SStefano Zampini 
1502674ae819SStefano Zampini #undef __FUNCT__
1503c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1504c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1505c8587f34SStefano Zampini {
15068629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1507c8587f34SStefano Zampini   PetscErrorCode ierr;
1508c8587f34SStefano Zampini 
1509c8587f34SStefano Zampini   PetscFunctionBegin;
1510f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
15115e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1512c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1513c8587f34SStefano Zampini 
1514684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
15150fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1516684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1517c8587f34SStefano Zampini 
15188629588bSStefano Zampini   /*
15198629588bSStefano Zampini      Setup local correction and local part of coarse basis.
15208629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
15218629588bSStefano Zampini   */
152247f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
15238629588bSStefano Zampini 
15248629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
15258629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
15268629588bSStefano Zampini 
15278629588bSStefano Zampini   /* free */
15288629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1529c8587f34SStefano Zampini   PetscFunctionReturn(0);
1530c8587f34SStefano Zampini }
1531c8587f34SStefano Zampini 
1532c8587f34SStefano Zampini #undef __FUNCT__
1533674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1534674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1535674ae819SStefano Zampini {
1536674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1537674ae819SStefano Zampini   PetscErrorCode ierr;
1538674ae819SStefano Zampini 
1539674ae819SStefano Zampini   PetscFunctionBegin;
1540674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1541674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
154230368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1543674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1544785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1545674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1546f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1547f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1548785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
154963602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
155063602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1551674ae819SStefano Zampini   PetscFunctionReturn(0);
1552674ae819SStefano Zampini }
1553674ae819SStefano Zampini 
1554674ae819SStefano Zampini #undef __FUNCT__
1555674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1556674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1557674ae819SStefano Zampini {
1558674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15594f1b2e48SStefano Zampini   PetscInt       i;
1560674ae819SStefano Zampini   PetscErrorCode ierr;
1561674ae819SStefano Zampini 
1562674ae819SStefano Zampini   PetscFunctionBegin;
1563b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1564674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
156516909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
15661dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
1567674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1568674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
15694f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
15704f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
15714f1b2e48SStefano Zampini   }
15724f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1573b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1574674ae819SStefano Zampini   PetscFunctionReturn(0);
1575674ae819SStefano Zampini }
1576674ae819SStefano Zampini 
1577674ae819SStefano Zampini #undef __FUNCT__
1578674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1579674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1580674ae819SStefano Zampini {
1581674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1582674ae819SStefano Zampini   PetscErrorCode ierr;
1583674ae819SStefano Zampini 
1584674ae819SStefano Zampini   PetscFunctionBegin;
1585674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
158658da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1587ca92afb2SStefano Zampini     PetscScalar *array;
158806656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
158906656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
159058da7f69SStefano Zampini   }
1591674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1592674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
159315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
159415aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1595674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1596674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1597674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
159806656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1599674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1600674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
16018ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1602674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1603674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1604674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1605f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1606f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1607f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1608f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1609727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
16100e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1611f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
161270cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
161381d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
16140369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
16151dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
16164f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
16178b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1618ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1619ca92afb2SStefano Zampini     PetscInt i;
1620ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1621ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1622ca92afb2SStefano Zampini     }
1623ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1624ca92afb2SStefano Zampini   }
16254f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1626674ae819SStefano Zampini   PetscFunctionReturn(0);
1627674ae819SStefano Zampini }
1628674ae819SStefano Zampini 
1629674ae819SStefano Zampini #undef __FUNCT__
1630f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1631f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
16326bfb1811SStefano Zampini {
16336bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16346bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
16356bfb1811SStefano Zampini   VecType        impVecType;
16364f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
16376bfb1811SStefano Zampini   PetscErrorCode ierr;
16386bfb1811SStefano Zampini 
16396bfb1811SStefano Zampini   PetscFunctionBegin;
16406c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1641e7b262bdSStefano Zampini   /* get sizes */
16424f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1643b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
16446bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1645e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1646e7b262bdSStefano Zampini   /* R nodes */
1647e7b262bdSStefano Zampini   old_size = -1;
1648e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1649e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1650e7b262bdSStefano Zampini   }
1651e7b262bdSStefano Zampini   if (n_R != old_size) {
1652e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1653e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
16546bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
16556bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
16566bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
16576bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1658e7b262bdSStefano Zampini   }
1659e7b262bdSStefano Zampini   /* local primal dofs */
1660e7b262bdSStefano Zampini   old_size = -1;
1661e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1662e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1663e7b262bdSStefano Zampini   }
1664e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1665e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
166683b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1667e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
16686bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1669e7b262bdSStefano Zampini   }
1670e7b262bdSStefano Zampini   /* local explicit constraints */
1671e7b262bdSStefano Zampini   old_size = -1;
1672e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1673e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1674e7b262bdSStefano Zampini   }
1675e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1676e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
167783b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
167883b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
167983b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
168083b7ccabSStefano Zampini   }
16816bfb1811SStefano Zampini   PetscFunctionReturn(0);
16826bfb1811SStefano Zampini }
16836bfb1811SStefano Zampini 
16846bfb1811SStefano Zampini #undef __FUNCT__
168547f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
168647f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
168788ebb749SStefano Zampini {
168825084f0cSStefano Zampini   PetscErrorCode  ierr;
168925084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
169088ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
169188ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1692d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
169325084f0cSStefano Zampini   /* submatrices of local problem */
169480677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
169506656605SStefano Zampini   /* submatrices of local coarse problem */
169606656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
169725084f0cSStefano Zampini   /* working matrices */
169806656605SStefano Zampini   Mat             C_CR;
169925084f0cSStefano Zampini   /* additional working stuff */
170006656605SStefano Zampini   PC              pc_R;
17014f1b2e48SStefano Zampini   Mat             F;
17025cbda25cSStefano Zampini   Vec             dummy_vec;
1703a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
170425084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
170506656605SStefano Zampini   PetscScalar     *work;
170606656605SStefano Zampini   PetscInt        *idx_V_B;
1707ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
170806656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1709ffd830a3SStefano Zampini 
171025084f0cSStefano Zampini   /* some shortcuts to scalars */
171106656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
171288ebb749SStefano Zampini 
171388ebb749SStefano Zampini   PetscFunctionBegin;
1714ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1715ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1716ffd830a3SStefano Zampini   }
1717ffd830a3SStefano Zampini 
1718ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1719b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
17204f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1721b371cd4fSStefano Zampini   n_B = pcis->n_B;
1722b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
172388ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
172488ebb749SStefano Zampini 
172588ebb749SStefano Zampini   /* vertices in boundary numbering */
1726785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
17270e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
17286c4ed002SBarry 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);
172988ebb749SStefano Zampini 
173006656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1731019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
173206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
173306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
173406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
173506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
173606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
173706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
173806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
173906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
174006656605SStefano Zampini 
174106656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
174206656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
174306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
174406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
174506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1746ffd830a3SStefano Zampini   lda_rhs = n_R;
1747a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
174806656605SStefano Zampini   if (isLU || isILU || isCHOL) {
174906656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1750df4d28bfSStefano Zampini   } else if (sub_schurs->reuse_solver) {
1751df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1752d62866d3SStefano Zampini     MatFactorType      type;
1753d62866d3SStefano Zampini 
1754df4d28bfSStefano Zampini     F = reuse_solver->F;
17556816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1756d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1757ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
175822db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
175906656605SStefano Zampini   } else {
176006656605SStefano Zampini     F = NULL;
176106656605SStefano Zampini   }
176206656605SStefano Zampini 
1763ffd830a3SStefano Zampini   /* allocate workspace */
1764ffd830a3SStefano Zampini   n = 0;
1765ffd830a3SStefano Zampini   if (n_constraints) {
1766ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1767ffd830a3SStefano Zampini   }
1768ffd830a3SStefano Zampini   if (n_vertices) {
1769ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1770ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1771ffd830a3SStefano Zampini   }
1772ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1773ffd830a3SStefano Zampini 
17745cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
17755cbda25cSStefano Zampini   dummy_vec = NULL;
17765cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
17775cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
17785cbda25cSStefano Zampini   }
17795cbda25cSStefano Zampini 
178088ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
178188ebb749SStefano Zampini   if (n_constraints) {
178272b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
178306656605SStefano Zampini     IS          is_aux;
178480677318SStefano Zampini     PetscScalar *array,*array2;
178506656605SStefano Zampini 
1786f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
178780677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
178888ebb749SStefano Zampini 
178925084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
179025084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
17918ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
179272b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
179388ebb749SStefano Zampini 
179480677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
179580677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1796ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
179788ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
179806656605SStefano Zampini       const PetscScalar *row_cmat_values;
179906656605SStefano Zampini       const PetscInt    *row_cmat_indices;
180006656605SStefano Zampini       PetscInt          size_of_constraint,j;
180188ebb749SStefano Zampini 
180206656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
180306656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1804ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
180506656605SStefano Zampini       }
180606656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
180706656605SStefano Zampini     }
1808ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
180906656605SStefano Zampini     if (F) {
181006656605SStefano Zampini       Mat B;
181106656605SStefano Zampini 
1812ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1813a3df083aSStefano Zampini       if (need_benign_correction) {
1814df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1815a3df083aSStefano Zampini 
181672b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
181772b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1818a3df083aSStefano Zampini       }
181980677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1820a3df083aSStefano Zampini       if (need_benign_correction) {
1821a3df083aSStefano Zampini         PetscScalar        *marr;
1822df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1823a3df083aSStefano Zampini 
1824a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
18255cbda25cSStefano Zampini         if (lda_rhs != n_R) {
18265cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
18275cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
18285cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
18295cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
18305cbda25cSStefano Zampini           }
18315cbda25cSStefano Zampini         } else {
1832a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
1833a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
18345cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
1835a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1836a3df083aSStefano Zampini           }
18375cbda25cSStefano Zampini         }
1838a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1839a3df083aSStefano Zampini       }
184006656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
184106656605SStefano Zampini     } else {
184280677318SStefano Zampini       PetscScalar *marr;
184380677318SStefano Zampini 
184480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
184506656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1846ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1847ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
184806656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
184906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
185006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
185106656605SStefano Zampini       }
185280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
185306656605SStefano Zampini     }
185480677318SStefano Zampini     if (!pcbddc->switch_static) {
185580677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
185680677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
185780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
185880677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1859ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
186080677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
186180677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
186280677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
186380677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
186480677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
186580677318SStefano Zampini       }
186680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
186780677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
186872b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
186980677318SStefano Zampini     } else {
1870ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1871ffd830a3SStefano Zampini         IS dummy;
1872ffd830a3SStefano Zampini 
1873ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
187472b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1875ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1876ffd830a3SStefano Zampini       } else {
187780677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
187880677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1879ffd830a3SStefano Zampini       }
188025084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
188180677318SStefano Zampini     }
188280677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
188380677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
188480677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
188506656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
188606656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
188780677318SStefano Zampini     if (isCHOL) {
188880677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
188980677318SStefano Zampini     } else {
189025084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
189180677318SStefano Zampini     }
189280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
189306656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
189425084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
189525084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
189625084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
189780677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
189872b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
189972b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
190006656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
190106656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1902f4ddd8eeSStefano Zampini   }
1903fc227af8SStefano Zampini 
1904fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
190588ebb749SStefano Zampini   if (n_vertices) {
190606656605SStefano Zampini     IS is_aux;
19073a50541eSStefano Zampini 
1908df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
19096816873aSStefano Zampini       IS tis;
19106816873aSStefano Zampini 
19116816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
19126816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
19136816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
19146816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
19156816873aSStefano Zampini     } else {
19163a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
19176816873aSStefano Zampini     }
19189577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
19199577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
192004708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
192125084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
192288ebb749SStefano Zampini   }
192388ebb749SStefano Zampini 
192488ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1925f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
192606656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
192706656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
192806656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
192906656605SStefano Zampini     }
1930f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
193106656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
193206656605SStefano Zampini       PetscScalar *marray;
193306656605SStefano Zampini 
193406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
193506656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1936f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1937f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1938f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1939f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1940f4ddd8eeSStefano Zampini     }
1941f4ddd8eeSStefano Zampini   }
194206656605SStefano Zampini 
1943f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
194406656605SStefano Zampini     PetscScalar *marray;
194588ebb749SStefano Zampini 
194606656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
19478eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
194806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
194988ebb749SStefano Zampini     }
19503301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
195106656605SStefano Zampini       n *= 2;
195288ebb749SStefano Zampini     }
195306656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
195406656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
195506656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
19568eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
195706656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
195806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
195988ebb749SStefano Zampini     }
19603301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
196106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
19628eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
196306656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
196406656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
196588ebb749SStefano Zampini       }
196688ebb749SStefano Zampini     } else {
1967c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1968c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
19691b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1970c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1971c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1972c0553b1fSStefano Zampini       }
197388ebb749SStefano Zampini     }
197406656605SStefano Zampini   }
1975019a44ceSStefano Zampini 
197606656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
19774f1b2e48SStefano Zampini   p0_lidx_I = NULL;
19784f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1979d12edf2fSStefano Zampini     const PetscInt *idxs;
1980d12edf2fSStefano Zampini 
1981d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
19824f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
19834f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
19844f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
19854f1b2e48SStefano Zampini     }
1986d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1987d12edf2fSStefano Zampini   }
1988d16cbb6bSStefano Zampini 
198906656605SStefano Zampini   /* vertices */
199006656605SStefano Zampini   if (n_vertices) {
199116f15bc4SStefano Zampini 
1992af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
199304708bb6SStefano Zampini 
199416f15bc4SStefano Zampini     if (n_R) {
199514393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
199606656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
199716f15bc4SStefano Zampini       PetscScalar  *x,*y;
199804708bb6SStefano Zampini       PetscBool    isseqaij;
199906656605SStefano Zampini 
200021eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
200114393ed6SStefano Zampini       if (need_benign_correction) {
200214393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
200314393ed6SStefano Zampini         IS                     is_p0;
200414393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
200514393ed6SStefano Zampini 
200614393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
200714393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
200814393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
2009af25d912SStefano 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);
201014393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
201114393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
201214393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
201314393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
201414393ed6SStefano Zampini       }
201514393ed6SStefano Zampini 
2016ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
2017af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2018ffd830a3SStefano Zampini       } else {
2019ca92afb2SStefano Zampini         PetscScalar    *av,*array;
2020ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
2021ca92afb2SStefano Zampini         PetscInt       n;
2022ca92afb2SStefano Zampini         PetscBool      flg_row;
2023ffd830a3SStefano Zampini 
2024ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
2025ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
20269d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2027ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2028ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
2029ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
2030ca92afb2SStefano Zampini           PetscInt j;
2031ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
2032ffd830a3SStefano Zampini         }
2033ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2034ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2035ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
2036ffd830a3SStefano Zampini       }
2037ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2038a3df083aSStefano Zampini       if (need_benign_correction) {
2039df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2040a3df083aSStefano Zampini         PetscScalar        *marr;
2041a3df083aSStefano Zampini 
2042a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
204314393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
204414393ed6SStefano Zampini 
204514393ed6SStefano Zampini                | 0 0  0 | (V)
204614393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
204714393ed6SStefano Zampini                | 0 0 -1 | (p0)
204814393ed6SStefano Zampini 
204914393ed6SStefano Zampini         */
2050df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
205114393ed6SStefano Zampini           const PetscScalar *vals;
205214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
205314393ed6SStefano Zampini           PetscInt          n,j,nz;
205414393ed6SStefano Zampini 
2055df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2056df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
205714393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
205814393ed6SStefano Zampini           for (j=0;j<n;j++) {
205914393ed6SStefano Zampini             PetscScalar val = vals[j];
206014393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
206114393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
206214393ed6SStefano Zampini           }
206314393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2064df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
206514393ed6SStefano Zampini         }
206672b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
206772b8c272SStefano Zampini       }
206872b8c272SStefano Zampini       if (F) {
206914393ed6SStefano Zampini         /* need to correct the rhs */
207072b8c272SStefano Zampini         if (need_benign_correction) {
207172b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
207272b8c272SStefano Zampini           PetscScalar        *marr;
207372b8c272SStefano Zampini 
207472b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
20755cbda25cSStefano Zampini           if (lda_rhs != n_R) {
20765cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
20775cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
20785cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
20795cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
20805cbda25cSStefano Zampini             }
20815cbda25cSStefano Zampini           } else {
2082a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2083a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
20845cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2085a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2086a3df083aSStefano Zampini             }
20875cbda25cSStefano Zampini           }
2088a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
2089a3df083aSStefano Zampini         }
209006656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
209114393ed6SStefano Zampini         /* need to correct the solution */
2092a3df083aSStefano Zampini         if (need_benign_correction) {
2093df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2094a3df083aSStefano Zampini           PetscScalar        *marr;
2095a3df083aSStefano Zampini 
2096a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
20975cbda25cSStefano Zampini           if (lda_rhs != n_R) {
20985cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
20995cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
21005cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
21015cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
21025cbda25cSStefano Zampini             }
21035cbda25cSStefano Zampini           } else {
2104a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2105a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
21065cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2107a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2108a3df083aSStefano Zampini             }
21095cbda25cSStefano Zampini           }
2110a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
2111a3df083aSStefano Zampini         }
211206656605SStefano Zampini       } else {
211306656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
211406656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
2115ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
2116ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
211706656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
211806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
211906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
212006656605SStefano Zampini         }
212106656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
212206656605SStefano Zampini       }
212380677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2124ffd830a3SStefano Zampini       /* S_VV and S_CV */
212506656605SStefano Zampini       if (n_constraints) {
212606656605SStefano Zampini         Mat B;
212780677318SStefano Zampini 
2128ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
212980677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
2130ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
2131ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
213280677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213380677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213480677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
213580677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
213680677318SStefano Zampini         }
2137ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
213880677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
213980677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
2140ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
214180677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
214206656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
2143ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
2144ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
214506656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
214606656605SStefano Zampini       }
214704708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
214804708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
2149511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
215004708bb6SStefano Zampini       }
2151ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
2152ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
2153ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2154ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
2155ffd830a3SStefano Zampini       }
215606656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
215714393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
215814393ed6SStefano Zampini       if (need_benign_correction) {
2159df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
216014393ed6SStefano Zampini         PetscScalar      *marr,*sums;
216114393ed6SStefano Zampini 
216214393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
216314393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
2164df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
216514393ed6SStefano Zampini           const PetscScalar *vals;
216614393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
216714393ed6SStefano Zampini           PetscInt          n,j,nz;
216814393ed6SStefano Zampini 
2169df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2170df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
217114393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
217214393ed6SStefano Zampini             PetscInt k;
217314393ed6SStefano Zampini             sums[j] = 0.;
217414393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
217514393ed6SStefano Zampini           }
217614393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
217714393ed6SStefano Zampini           for (j=0;j<n;j++) {
217814393ed6SStefano Zampini             PetscScalar val = vals[j];
217914393ed6SStefano Zampini             PetscInt k;
218014393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
218114393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
218214393ed6SStefano Zampini             }
218314393ed6SStefano Zampini           }
218414393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2185df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
218614393ed6SStefano Zampini         }
218714393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
218814393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
218914393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
219014393ed6SStefano Zampini       }
219180677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
219206656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
219306656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
219406656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
219506656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
219606656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
219706656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
219806656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2199d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
2200019a44ceSStefano Zampini     } else {
2201d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2202d16cbb6bSStefano Zampini     }
220321eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
2204d16cbb6bSStefano Zampini 
220506656605SStefano Zampini     /* coarse basis functions */
220606656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
220716f15bc4SStefano Zampini       PetscScalar *y;
220816f15bc4SStefano Zampini 
2209ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
221006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
221106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
221206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
221306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
221406656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
221506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
221606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
221706656605SStefano Zampini 
221806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
22194f1b2e48SStefano Zampini         PetscInt j;
22204f1b2e48SStefano Zampini 
222106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
222206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
222306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
222406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
222506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
22264f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
222706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
222806656605SStefano Zampini       }
222906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
223006656605SStefano Zampini     }
223104708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
223204708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
223306656605SStefano Zampini   }
22345cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
223506656605SStefano Zampini 
223606656605SStefano Zampini   if (n_constraints) {
223706656605SStefano Zampini     Mat B;
223806656605SStefano Zampini 
2239ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
224006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
224180677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
224206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
224306656605SStefano Zampini     if (n_vertices) {
224480677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
224580677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
224680677318SStefano Zampini       } else {
224780677318SStefano Zampini         Mat S_VCt;
224880677318SStefano Zampini 
2249ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
2250ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
225172b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
2252ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
2253ffd830a3SStefano Zampini         }
225480677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
225580677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
225680677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
225780677318SStefano Zampini       }
225806656605SStefano Zampini     }
225906656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
226006656605SStefano Zampini     /* coarse basis functions */
226106656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
226206656605SStefano Zampini       PetscScalar *y;
226306656605SStefano Zampini 
2264ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
226506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
226606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
226706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
226806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
226906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
227006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
227106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
22724f1b2e48SStefano Zampini         PetscInt j;
22734f1b2e48SStefano Zampini 
227406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
227506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
227606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
227706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
227806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
22794f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
228006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
228106656605SStefano Zampini       }
228206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
228306656605SStefano Zampini     }
228406656605SStefano Zampini   }
228580677318SStefano Zampini   if (n_constraints) {
228680677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
228780677318SStefano Zampini   }
22884f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
228972b8c272SStefano Zampini 
229072b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
229172b8c272SStefano Zampini   if (pcbddc->benign_n) {
229272b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
229372b8c272SStefano Zampini     IS          is_dummy;
229472b8c272SStefano Zampini     PetscScalar *data;
229572b8c272SStefano Zampini     PetscInt    j;
229672b8c272SStefano Zampini 
229772b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
229872b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
229972b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
230072b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
230186c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
230272b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
230372b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
230472b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
230572b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
230672b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
230772b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
230872b8c272SStefano Zampini       }
230972b8c272SStefano Zampini     }
231072b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
231172b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
231272b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
231372b8c272SStefano Zampini   }
2314019a44ceSStefano Zampini 
231506656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
23163301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
2317ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
2318ffd830a3SStefano Zampini     PetscScalar *marray;
231906656605SStefano Zampini 
232006656605SStefano Zampini     if (n_constraints) {
2321ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
232206656605SStefano Zampini 
2323af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
232406656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
2325ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
232616f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
232706656605SStefano Zampini       if (n_vertices) {
2328ffd830a3SStefano Zampini         Mat S_VCT;
232906656605SStefano Zampini 
233006656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
2331ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
233216f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
233306656605SStefano Zampini       }
2334ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
2335*5b782168SStefano Zampini     } else {
2336*5b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
233706656605SStefano Zampini     }
233816f15bc4SStefano Zampini     if (n_vertices && n_R) {
2339ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2340ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2341ffd830a3SStefano Zampini       PetscInt       n;
2342ffd830a3SStefano Zampini       PetscBool      flg_row;
234306656605SStefano Zampini 
2344ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2345af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
2346ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2347ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2348ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2349ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2350ffd830a3SStefano Zampini         PetscInt j;
2351ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2352ffd830a3SStefano Zampini       }
2353ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2354ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2355ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
235606656605SStefano Zampini     }
235706656605SStefano Zampini 
2358ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2359ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2360ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2361ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2362ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
236306656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
236406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
236506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
236606656605SStefano Zampini     }
2367ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2368*5b782168SStefano Zampini     if (B_C) {
2369ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2370ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2371ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2372ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2373ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2374ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2375ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
237606656605SStefano Zampini       }
2377ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
2378*5b782168SStefano Zampini     }
2379*5b782168SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2380*5b782168SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2381*5b782168SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2382*5b782168SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2383*5b782168SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2384*5b782168SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
2385*5b782168SStefano Zampini     }
2386*5b782168SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
238706656605SStefano Zampini     /* coarse basis functions */
238806656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
238906656605SStefano Zampini       PetscScalar *y;
239006656605SStefano Zampini 
2391ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
239206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
239306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
239406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
239506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
239606656605SStefano Zampini       if (i<n_vertices) {
239706656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
239806656605SStefano Zampini       }
239906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
240006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
240106656605SStefano Zampini 
240206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
240306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
240406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
240506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
240606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
240706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
240806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
240906656605SStefano Zampini       }
241006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
241106656605SStefano Zampini     }
2412ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2413ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
241406656605SStefano Zampini   }
2415d62866d3SStefano Zampini   /* free memory */
241688ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
241706656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
241806656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
241906656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
242006656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2421d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2422d62866d3SStefano Zampini   if (n_vertices) {
2423d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2424d62866d3SStefano Zampini   }
2425d62866d3SStefano Zampini   if (n_constraints) {
2426d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2427d62866d3SStefano Zampini   }
242888ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
242988ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
243088ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2431d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
243288ebb749SStefano Zampini     Mat         coarse_sub_mat;
243325084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
243488ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
243588ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
243688ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
24378bec7fa6SStefano Zampini     Mat         C_B,CPHI;
24388bec7fa6SStefano Zampini     IS          is_dummy;
24398bec7fa6SStefano Zampini     Vec         mones;
244088ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
244188ebb749SStefano Zampini     PetscReal   real_value;
244288ebb749SStefano Zampini 
2443a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2444a3df083aSStefano Zampini       Mat A;
2445a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2446a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2447a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2448a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2449a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2450a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2451a3df083aSStefano Zampini     } else {
245288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
245388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
245488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
245588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2456a3df083aSStefano Zampini     }
245788ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
245888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2459ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
246088ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
246188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
246288ebb749SStefano Zampini     }
246388ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
246488ebb749SStefano Zampini 
246525084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
24663301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
246725084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2468ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
246988ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
247088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
247188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
247288ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
247388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
247488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
247588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
247688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
247788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
247888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
247988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
248088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
248188ebb749SStefano Zampini     } else {
248288ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
248388ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
248488ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
248588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
248688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
248788ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
248888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
248988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
249088ebb749SStefano Zampini     }
249188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
249288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
249388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2494511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
24954f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2496fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
2497d12edf2fSStefano Zampini       PetscScalar *data,*data2;
24984f1b2e48SStefano Zampini       PetscInt    j;
2499d12edf2fSStefano Zampini 
25004f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2501fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
2502d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
250386c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2504d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2505d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
25064f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
25074f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2508d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
25094f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
25104f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
25114f1b2e48SStefano Zampini         }
2512d12edf2fSStefano Zampini       }
2513d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2514d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2515d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2516d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2517d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2518d12edf2fSStefano Zampini     }
2519d12edf2fSStefano Zampini #if 0
2520d12edf2fSStefano Zampini   {
2521d12edf2fSStefano Zampini     PetscViewer viewer;
2522d12edf2fSStefano Zampini     char filename[256];
2523ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2524d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2525d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2526ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2527ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2528ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2529d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
253072b8c272SStefano Zampini     if (save_change) {
253172b8c272SStefano Zampini       Mat phi_B;
253272b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
253372b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
253472b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
253572b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
253672b8c272SStefano Zampini     } else {
2537ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2538ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
253972b8c272SStefano Zampini     }
2540ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2541ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2542ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2543ffd830a3SStefano Zampini     }
2544ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2545ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2546ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2547ffd830a3SStefano Zampini     }
254872b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
2549ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2550ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2551ffd830a3SStefano Zampini     }
2552d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2553d12edf2fSStefano Zampini   }
2554d12edf2fSStefano Zampini #endif
255581d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
25568bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
25571575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
255806656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
25598bec7fa6SStefano Zampini 
25608bec7fa6SStefano Zampini     /* check constraints */
2561a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2562a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
25634f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
25648bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2565a00504b5SStefano Zampini     } else {
2566a00504b5SStefano Zampini       PetscScalar *data;
2567a00504b5SStefano Zampini       Mat         tmat;
2568a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2569a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
2570a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2571a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2572a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2573a00504b5SStefano Zampini     }
25748bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
25758bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
25768bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
25778bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2578bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2579ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
2580bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2581bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2582bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2583bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2584bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
258588ebb749SStefano Zampini     }
25868bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
25878bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
25888bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
25898bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
259025084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
259188ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
259288ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
259388ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
259488ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
259588ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
259688ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
259788ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
259888ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
259988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
260088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2601ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
260288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
260388ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
260488ebb749SStefano Zampini     }
260588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
260688ebb749SStefano Zampini   }
26078629588bSStefano Zampini   /* get back data */
26088629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
260988ebb749SStefano Zampini   PetscFunctionReturn(0);
261088ebb749SStefano Zampini }
261188ebb749SStefano Zampini 
261288ebb749SStefano Zampini #undef __FUNCT__
2613d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2614d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2615aa0d41d4SStefano Zampini {
2616d65f70fdSStefano Zampini   Mat            *work_mat;
2617d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2618d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2619c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
2620aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2621aa0d41d4SStefano Zampini 
2622aa0d41d4SStefano Zampini   PetscFunctionBegin;
2623d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2624d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2625d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2626d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2627aa0d41d4SStefano Zampini 
2628d65f70fdSStefano Zampini   if (!rsorted) {
2629906d46d4SStefano Zampini     const PetscInt *idxs;
2630906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2631aa0d41d4SStefano Zampini 
2632d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2633d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2634d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2635d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2636aa0d41d4SStefano Zampini     }
2637d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2638d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2639d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2640d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2641aa0d41d4SStefano Zampini     }
2642d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2643d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2644d65f70fdSStefano Zampini   } else {
2645d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2646d65f70fdSStefano Zampini     isrow_s = isrow;
2647aa0d41d4SStefano Zampini   }
2648906d46d4SStefano Zampini 
2649d65f70fdSStefano Zampini   if (!csorted) {
2650d65f70fdSStefano Zampini     if (isrow == iscol) {
2651d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2652d65f70fdSStefano Zampini       iscol_s = isrow_s;
2653d65f70fdSStefano Zampini     } else {
2654d65f70fdSStefano Zampini       const PetscInt *idxs;
2655d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
2656906d46d4SStefano Zampini 
2657d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2658d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2659d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2660d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2661d65f70fdSStefano Zampini       }
2662d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2663d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2664d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2665d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2666d65f70fdSStefano Zampini       }
2667d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2668d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2669d65f70fdSStefano Zampini     }
2670d65f70fdSStefano Zampini   } else {
2671d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2672d65f70fdSStefano Zampini     iscol_s = iscol;
2673d65f70fdSStefano Zampini   }
2674d65f70fdSStefano Zampini 
2675d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2676d65f70fdSStefano Zampini 
2677d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2678906d46d4SStefano Zampini     Mat      new_mat;
2679d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2680906d46d4SStefano Zampini 
2681d65f70fdSStefano Zampini     if (!rsorted) {
2682d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2683d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2684d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2685d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2686906d46d4SStefano Zampini       }
2687d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2688d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2689d65f70fdSStefano Zampini     } else {
2690d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2691906d46d4SStefano Zampini     }
2692d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2693d65f70fdSStefano Zampini 
2694d65f70fdSStefano Zampini     if (!csorted) {
2695d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2696d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2697d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2698d65f70fdSStefano Zampini       } else {
2699d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2700d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2701d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2702d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2703d65f70fdSStefano Zampini         }
2704d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2705d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2706d65f70fdSStefano Zampini       }
2707d65f70fdSStefano Zampini     } else {
2708d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2709d65f70fdSStefano Zampini     }
2710d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2711d65f70fdSStefano Zampini 
2712d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2713d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2714d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2715d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2716d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2717d65f70fdSStefano Zampini   }
2718d65f70fdSStefano Zampini 
2719d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2720d65f70fdSStefano Zampini   *B = work_mat[0];
2721d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2722d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2723d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2724d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2725d65f70fdSStefano Zampini }
2726d65f70fdSStefano Zampini 
2727d65f70fdSStefano Zampini #undef __FUNCT__
27285e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
27295e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2730aa0d41d4SStefano Zampini {
2731aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
27325e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2733d65f70fdSStefano Zampini   Mat            new_mat;
27345e8657edSStefano Zampini   IS             is_local,is_global;
2735d65f70fdSStefano Zampini   PetscInt       local_size;
2736d65f70fdSStefano Zampini   PetscBool      isseqaij;
2737aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2738aa0d41d4SStefano Zampini 
2739aa0d41d4SStefano Zampini   PetscFunctionBegin;
2740aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
27415e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
27425e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2743b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2744aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2745d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2746aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2747906d46d4SStefano Zampini 
2748906d46d4SStefano Zampini   /* check */
2749906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2750906d46d4SStefano Zampini     Vec       x,x_change;
2751906d46d4SStefano Zampini     PetscReal error;
2752906d46d4SStefano Zampini 
27535e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2754906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
27555e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2756e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2757e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2758d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2759e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2760e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2761906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2762906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2763906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2764906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2765906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2766906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2767906d46d4SStefano Zampini   }
2768906d46d4SStefano Zampini 
276922d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
27709b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
277122d5777bSStefano Zampini   if (isseqaij) {
2772a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2773a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2774aa0d41d4SStefano Zampini   } else {
2775a00504b5SStefano Zampini     Mat work_mat;
27761cf9b237SStefano Zampini 
2777a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2778aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2779a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
27801d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2781aa0d41d4SStefano Zampini   }
27823301b35fSStefano Zampini   if (matis->A->symmetric_set) {
27833301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2784e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
27853301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2786e496cd5dSStefano Zampini #endif
27873301b35fSStefano Zampini   }
2788d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2789aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2790aa0d41d4SStefano Zampini }
2791aa0d41d4SStefano Zampini 
2792aa0d41d4SStefano Zampini #undef __FUNCT__
2793a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
27948ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2795a64d13efSStefano Zampini {
2796a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2797a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2798d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
279953892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
28003a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
28013a50541eSStefano Zampini   PetscInt        vbs,bs;
28026816873aSStefano Zampini   PetscBT         bitmask=NULL;
2803a64d13efSStefano Zampini   PetscErrorCode  ierr;
2804a64d13efSStefano Zampini 
2805a64d13efSStefano Zampini   PetscFunctionBegin;
2806b23d619eSStefano Zampini   /*
2807b23d619eSStefano Zampini     No need to setup local scatters if
2808b23d619eSStefano Zampini       - primal space is unchanged
2809b23d619eSStefano Zampini         AND
2810b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2811b23d619eSStefano Zampini         AND
2812b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2813b23d619eSStefano Zampini   */
2814b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2815f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2816f4ddd8eeSStefano Zampini   }
2817f4ddd8eeSStefano Zampini   /* destroy old objects */
2818f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2819f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2820f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2821a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2822b371cd4fSStefano Zampini   n_B = pcis->n_B;
2823b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2824b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
28253a50541eSStefano Zampini 
2826a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
28276816873aSStefano Zampini 
282853892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2829df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
2830854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2831a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2832a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
28330e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2834a64d13efSStefano Zampini     }
2835a64d13efSStefano Zampini 
2836a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
28374641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
28386816873aSStefano Zampini         idx_R_local[n_R++] = i;
2839a64d13efSStefano Zampini       }
2840a64d13efSStefano Zampini     }
2841df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2842df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
28436816873aSStefano Zampini 
2844df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2845df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
28466816873aSStefano Zampini   }
28473a50541eSStefano Zampini 
28483a50541eSStefano Zampini   /* Block code */
28493a50541eSStefano Zampini   vbs = 1;
28503a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
28513a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
28523a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
28533a50541eSStefano Zampini     PetscInt  *vary;
2854df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
2855785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
28563a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2857d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2858d3df7717SStefano 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 */
28590e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2860d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
28613a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
28623a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
28633a50541eSStefano Zampini           break;
28643a50541eSStefano Zampini         }
28653a50541eSStefano Zampini       }
2866d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2867d3df7717SStefano Zampini     } else {
2868d3df7717SStefano Zampini       /* Verify directly the R set */
2869d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2870d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2871d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2872d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2873d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2874d3df7717SStefano Zampini             break;
2875d3df7717SStefano Zampini           }
2876d3df7717SStefano Zampini         }
2877d3df7717SStefano Zampini       }
2878d3df7717SStefano Zampini     }
28793a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
28803a50541eSStefano Zampini       vbs = bs;
28813a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
28823a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
28833a50541eSStefano Zampini       }
28843a50541eSStefano Zampini     }
28853a50541eSStefano Zampini   }
28863a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2887df4d28bfSStefano Zampini   if (sub_schurs->reuse_solver) {
2888df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
288953892102SStefano Zampini 
2890df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2891df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
289253892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2893df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
289453892102SStefano Zampini   } else {
28953a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
289653892102SStefano Zampini   }
2897a64d13efSStefano Zampini 
2898a64d13efSStefano Zampini   /* print some info if requested */
2899a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2900a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2901a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
29021575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2903a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2904a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
29054f1b2e48SStefano 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);
2906a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2907a64d13efSStefano Zampini   }
2908a64d13efSStefano Zampini 
2909a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
2910df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
29116816873aSStefano Zampini     IS       is_aux1,is_aux2;
29126816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
29136816873aSStefano Zampini 
29143a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2915854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2916854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2917a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
29184641a718SStefano Zampini     for (i=0; i<n_D; i++) {
29194641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
29204641a718SStefano Zampini     }
2921a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2922a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
29234641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
29244641a718SStefano Zampini         aux_array1[j++] = i;
2925a64d13efSStefano Zampini       }
2926a64d13efSStefano Zampini     }
2927a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2928a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2929a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
29304641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
29314641a718SStefano Zampini         aux_array2[j++] = i;
2932a64d13efSStefano Zampini       }
2933a64d13efSStefano Zampini     }
2934a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2935a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2936a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2937a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2938a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2939a64d13efSStefano Zampini 
29408eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2941785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2942a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
29434641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
29444641a718SStefano Zampini           aux_array1[j++] = i;
2945a64d13efSStefano Zampini         }
2946a64d13efSStefano Zampini       }
2947a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2948a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2949a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2950a64d13efSStefano Zampini     }
29514641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
29523a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2953d62866d3SStefano Zampini   } else {
2954df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
29556816873aSStefano Zampini     IS                 tis;
29566816873aSStefano Zampini     PetscInt           schur_size;
29576816873aSStefano Zampini 
2958df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
29596816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
2960df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
29616816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
29626816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
29636816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
29646816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
29656816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2966d62866d3SStefano Zampini     }
2967d62866d3SStefano Zampini   }
2968a64d13efSStefano Zampini   PetscFunctionReturn(0);
2969a64d13efSStefano Zampini }
2970a64d13efSStefano Zampini 
2971304d26faSStefano Zampini 
2972304d26faSStefano Zampini #undef __FUNCT__
2973304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2974684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2975304d26faSStefano Zampini {
2976304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2977304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2978304d26faSStefano Zampini   PC             pc_temp;
2979304d26faSStefano Zampini   Mat            A_RR;
2980f4ddd8eeSStefano Zampini   MatReuse       reuse;
2981304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2982304d26faSStefano Zampini   PetscReal      value;
298304708bb6SStefano Zampini   PetscInt       n_D,n_R;
2984c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
2985304d26faSStefano Zampini   PetscErrorCode ierr;
2986e604994aSStefano Zampini   /* prefixes stuff */
2987312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2988e604994aSStefano Zampini   size_t         len;
2989304d26faSStefano Zampini 
2990304d26faSStefano Zampini   PetscFunctionBegin;
2991304d26faSStefano Zampini 
2992e604994aSStefano Zampini   /* compute prefixes */
2993e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2994e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2995e604994aSStefano Zampini   if (!pcbddc->current_level) {
2996e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2997e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2998e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2999e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3000e604994aSStefano Zampini   } else {
3001e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3002312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3003e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3004e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
3005312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3006312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
300734d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
300834d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3009e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3010e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3011e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
3012e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
3013e604994aSStefano Zampini   }
3014e604994aSStefano Zampini 
3015304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
3016684f6988SStefano Zampini   if (dirichlet) {
3017d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3018450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3019450f8f5eSStefano Zampini       if (!sub_schurs->reuse_solver) {
3020450f8f5eSStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
3021450f8f5eSStefano Zampini       }
3022450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
3023a3df083aSStefano Zampini         Mat    A_IIn;
3024a3df083aSStefano Zampini 
3025a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
3026a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
3027a3df083aSStefano Zampini         pcis->A_II = A_IIn;
3028a3df083aSStefano Zampini       }
3029450f8f5eSStefano Zampini     }
30303301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
30313301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
3032964fefecSStefano Zampini     }
3033ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
3034964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
3035304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
3036304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
3037304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
3038304d26faSStefano Zampini       /* default */
3039304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3040e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
30419577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3042304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
30439577ea80SStefano Zampini       if (issbaij) {
30449577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
30459577ea80SStefano Zampini       } else {
3046304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
30479577ea80SStefano Zampini       }
3048304d26faSStefano Zampini       /* Allow user's customization */
3049304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3050304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3051304d26faSStefano Zampini     }
3052d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
3053df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
3054df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3055d62866d3SStefano Zampini 
3056df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
3057d5574798SStefano Zampini     }
3058304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3059304d26faSStefano Zampini     if (!n_D) {
3060304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
3061304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3062304d26faSStefano Zampini     }
3063304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
3064304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
3065304d26faSStefano Zampini     /* set ksp_D into pcis data */
3066304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
3067304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
3068304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
3069684f6988SStefano Zampini   }
3070304d26faSStefano Zampini 
3071304d26faSStefano Zampini   /* NEUMANN PROBLEM */
3072684f6988SStefano Zampini   A_RR = 0;
3073684f6988SStefano Zampini   if (neumann) {
3074d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
307504708bb6SStefano Zampini     PetscInt        ibs,mbs;
307604708bb6SStefano Zampini     PetscBool       issbaij;
307704708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
3078f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
30798ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
3080f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
3081f4ddd8eeSStefano Zampini       PetscInt nn_R;
308281d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
3083f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3084f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
3085f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
3086f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
3087f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3088f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3089f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
3090727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
3091f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3092f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
3093f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
3094f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
3095f4ddd8eeSStefano Zampini         }
3096f4ddd8eeSStefano Zampini       }
3097f4ddd8eeSStefano Zampini       /* last check */
3098d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
3099f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3100f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3101f4ddd8eeSStefano Zampini       }
3102f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
3103f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
3104f4ddd8eeSStefano Zampini     }
3105a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
3106af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3107af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
310804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
310904708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
311004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
311104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
311204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
3113af732b37SStefano Zampini       } else {
3114511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
31156816873aSStefano Zampini       }
311604708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
311704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
311804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
311904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
312004708bb6SStefano Zampini       } else {
3121511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
312204708bb6SStefano Zampini       }
312304708bb6SStefano Zampini     }
3124a00504b5SStefano Zampini     /* extract A_RR */
3125a00504b5SStefano Zampini     if (sub_schurs->reuse_solver) {
3126a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3127a00504b5SStefano Zampini 
3128a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
312916e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3130a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
313116e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
313216e386b8SStefano Zampini         } else {
3133a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
3134a00504b5SStefano Zampini         }
3135a00504b5SStefano Zampini       } else {
3136a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3137a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
3138a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3139a00504b5SStefano Zampini       }
3140a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
3141f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
314216e386b8SStefano Zampini     }
31433301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
31443301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
31456816873aSStefano Zampini     }
3146f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
3147304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
3148304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
3149304d26faSStefano Zampini       /* default */
3150304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3151e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
3152304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
31539577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
31549577ea80SStefano Zampini       if (issbaij) {
31559577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
31569577ea80SStefano Zampini       } else {
3157304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
31589577ea80SStefano Zampini       }
3159304d26faSStefano Zampini       /* Allow user's customization */
3160304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3161304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3162304d26faSStefano Zampini     }
3163304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3164304d26faSStefano Zampini     if (!n_R) {
3165304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
3166304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3167304d26faSStefano Zampini     }
31685cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
3169df4d28bfSStefano Zampini     /* Reuse solver if it is present */
3170df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
3171df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3172d62866d3SStefano Zampini 
3173df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
3174d62866d3SStefano Zampini     }
3175304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
3176304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
3177684f6988SStefano Zampini   }
3178304d26faSStefano Zampini 
3179684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
3180684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
31811575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3182684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3183684f6988SStefano Zampini   }
3184c7017625SStefano Zampini 
3185c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
3186c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
3187c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
3188c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
3189c7017625SStefano Zampini   }
3190c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
3191c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
3192c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
3193c7017625SStefano Zampini   }
3194c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
3195c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
3196c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
3197c7017625SStefano Zampini   }
3198c7017625SStefano Zampini 
3199c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
3200c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
3201684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
32020fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
32030fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
32040fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
32050fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
32060fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
3207e604994aSStefano 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);
3208c7017625SStefano Zampini       if (check_corr[0]) {
3209c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
3210c7017625SStefano Zampini       }
3211304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3212304d26faSStefano Zampini     }
3213684f6988SStefano Zampini     if (neumann) { /* Neumann */
32140fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
32150fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
32160fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
32170fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
32180fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
3219e604994aSStefano 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);
3220c7017625SStefano Zampini       if (check_corr[1]) {
3221c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
3222c7017625SStefano Zampini       }
3223304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3224304d26faSStefano Zampini     }
3225684f6988SStefano Zampini   }
32265cbda25cSStefano Zampini   /* free Neumann problem's matrix */
32275cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3228304d26faSStefano Zampini   PetscFunctionReturn(0);
3229304d26faSStefano Zampini }
3230304d26faSStefano Zampini 
3231304d26faSStefano Zampini #undef __FUNCT__
3232ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
323380677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
3234674ae819SStefano Zampini {
3235674ae819SStefano Zampini   PetscErrorCode  ierr;
3236674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3237be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3238674ae819SStefano Zampini 
3239674ae819SStefano Zampini   PetscFunctionBegin;
3240df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
324180677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
324220c7b377SStefano Zampini   }
324380677318SStefano Zampini   if (!pcbddc->switch_static) {
324480677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
324580677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
324680677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
324720c7b377SStefano Zampini     }
3248df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
324980677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
325080677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
325120c7b377SStefano Zampini     } else {
3252df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3253be83ff47SStefano Zampini 
3254df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3255df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
325620c7b377SStefano Zampini     }
3257be83ff47SStefano Zampini   } else {
325880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
325980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
326080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
326180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
326280677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
326380677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
326480677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
326580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
326680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3267674ae819SStefano Zampini     }
3268674ae819SStefano Zampini   }
326972b8c272SStefano Zampini   if (!sub_schurs->reuse_solver || pcbddc->switch_static) {
327080677318SStefano Zampini     if (applytranspose) {
327180677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
327280677318SStefano Zampini     } else {
327380677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
327480677318SStefano Zampini     }
3275be83ff47SStefano Zampini   } else {
3276df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3277be83ff47SStefano Zampini 
3278be83ff47SStefano Zampini     if (applytranspose) {
3279df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3280be83ff47SStefano Zampini     } else {
3281df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3282be83ff47SStefano Zampini     }
3283be83ff47SStefano Zampini   }
328480677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
328580677318SStefano Zampini   if (!pcbddc->switch_static) {
3286df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
328780677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
328880677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3289be83ff47SStefano Zampini     } else {
3290df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3291be83ff47SStefano Zampini 
3292df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3293df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3294be83ff47SStefano Zampini     }
329580677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
329680677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
329780677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
329880677318SStefano Zampini     }
329980677318SStefano Zampini   } else {
330080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
330180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
330280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
330380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
330480677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
330580677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
330680677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
330780677318SStefano Zampini     }
330880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
330980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
331080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
331180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3312674ae819SStefano Zampini   }
3313674ae819SStefano Zampini   PetscFunctionReturn(0);
3314674ae819SStefano Zampini }
3315674ae819SStefano Zampini 
3316dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
3317674ae819SStefano Zampini #undef __FUNCT__
3318674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
3319dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
3320674ae819SStefano Zampini {
3321674ae819SStefano Zampini   PetscErrorCode ierr;
3322674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3323674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
3324674ae819SStefano Zampini   const PetscScalar zero = 0.0;
3325674ae819SStefano Zampini 
3326674ae819SStefano Zampini   PetscFunctionBegin;
3327dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
33284fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3329dc359a40SStefano Zampini     if (applytranspose) {
3330674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
33318eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3332dc359a40SStefano Zampini     } else {
3333674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3334674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
333515aaf578SStefano Zampini     }
33364fee134fSStefano Zampini   } else {
33374fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
33384fee134fSStefano Zampini   }
3339efc2fbd9SStefano Zampini 
3340efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
33414f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
3342efc2fbd9SStefano Zampini     PetscScalar *array;
33434f1b2e48SStefano Zampini     PetscInt    j;
3344efc2fbd9SStefano Zampini 
3345efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
33464f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
3347efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3348efc2fbd9SStefano Zampini   }
3349efc2fbd9SStefano Zampini 
335012edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
335112edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
335212edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
335312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
335412edc857SStefano Zampini 
33559f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
335612edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
335751694757SStefano Zampini     Mat          coarse_mat;
3358964fefecSStefano Zampini     Vec          rhs,sol;
335951694757SStefano Zampini     MatNullSpace nullsp;
336027b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
3361964fefecSStefano Zampini 
336227b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
336327b6a85dSStefano Zampini       PC        coarse_pc;
336427b6a85dSStefano Zampini 
336527b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
336627b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
336727b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
336827b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
336927b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
337027b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
33713bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
337227b6a85dSStefano Zampini       }
337327b6a85dSStefano Zampini     }
3374964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3375964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
337651694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
337751694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
337851694757SStefano Zampini     if (nullsp) {
337951694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
338051694757SStefano Zampini     }
338112edc857SStefano Zampini     if (applytranspose) {
33821f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only) {
33831f4df5f7SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
33842701bc32SStefano Zampini       } else {
3385964fefecSStefano Zampini         ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
33862701bc32SStefano Zampini       }
33872701bc32SStefano Zampini     } else {
33881f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
33892701bc32SStefano Zampini         PC        coarse_pc;
33902701bc32SStefano Zampini 
33912701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
33922701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
33933e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
33942701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
339512edc857SStefano Zampini       } else {
3396964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
339712edc857SStefano Zampini       }
33982701bc32SStefano Zampini     }
33991d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
340027b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
340127b6a85dSStefano Zampini       PC        coarse_pc;
340227b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
340327b6a85dSStefano Zampini 
340427b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
340527b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
340627b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
34073bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
340827b6a85dSStefano Zampini     }
340951694757SStefano Zampini     if (nullsp) {
341051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
341151694757SStefano Zampini     }
341212edc857SStefano Zampini   }
3413674ae819SStefano Zampini 
3414674ae819SStefano Zampini   /* Local solution on R nodes */
34154fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
341680677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
34179f00e9b4SStefano Zampini   }
34189f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
34199f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
342012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3421674ae819SStefano Zampini 
34224fee134fSStefano Zampini   /* Sum contributions from the two levels */
34234fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3424dc359a40SStefano Zampini     if (applytranspose) {
3425dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3426dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3427dc359a40SStefano Zampini     } else {
3428674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
34298eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3430dc359a40SStefano Zampini     }
3431efc2fbd9SStefano Zampini     /* store p0 */
34324f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3433efc2fbd9SStefano Zampini       PetscScalar *array;
34344f1b2e48SStefano Zampini       PetscInt    j;
3435efc2fbd9SStefano Zampini 
3436efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
34374f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3438efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3439efc2fbd9SStefano Zampini     }
34404fee134fSStefano Zampini   } else { /* expand the coarse solution */
34414fee134fSStefano Zampini     if (applytranspose) {
34424fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
34434fee134fSStefano Zampini     } else {
34444fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
34454fee134fSStefano Zampini     }
34464fee134fSStefano Zampini   }
3447674ae819SStefano Zampini   PetscFunctionReturn(0);
3448674ae819SStefano Zampini }
3449674ae819SStefano Zampini 
3450674ae819SStefano Zampini #undef __FUNCT__
3451674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
345212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3453674ae819SStefano Zampini {
3454674ae819SStefano Zampini   PetscErrorCode ierr;
3455674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
345658da7f69SStefano Zampini   PetscScalar    *array;
345712edc857SStefano Zampini   Vec            from,to;
3458674ae819SStefano Zampini 
3459674ae819SStefano Zampini   PetscFunctionBegin;
346012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
346112edc857SStefano Zampini     from = pcbddc->coarse_vec;
346212edc857SStefano Zampini     to = pcbddc->vec1_P;
346312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
346412edc857SStefano Zampini       Vec tvec;
346558da7f69SStefano Zampini 
346658da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
346758da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
346812edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
346958da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
347058da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
347158da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
347212edc857SStefano Zampini     }
347312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
347412edc857SStefano Zampini     from = pcbddc->vec1_P;
347512edc857SStefano Zampini     to = pcbddc->coarse_vec;
347612edc857SStefano Zampini   }
347712edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3478674ae819SStefano Zampini   PetscFunctionReturn(0);
3479674ae819SStefano Zampini }
3480674ae819SStefano Zampini 
3481674ae819SStefano Zampini #undef __FUNCT__
3482674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
348312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3484674ae819SStefano Zampini {
3485674ae819SStefano Zampini   PetscErrorCode ierr;
3486674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
348758da7f69SStefano Zampini   PetscScalar    *array;
348812edc857SStefano Zampini   Vec            from,to;
3489674ae819SStefano Zampini 
3490674ae819SStefano Zampini   PetscFunctionBegin;
349112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
349212edc857SStefano Zampini     from = pcbddc->coarse_vec;
349312edc857SStefano Zampini     to = pcbddc->vec1_P;
349412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
349512edc857SStefano Zampini     from = pcbddc->vec1_P;
349612edc857SStefano Zampini     to = pcbddc->coarse_vec;
349712edc857SStefano Zampini   }
349812edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
349912edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
350012edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
350112edc857SStefano Zampini       Vec tvec;
350258da7f69SStefano Zampini 
350312edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
350458da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
350558da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
350658da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
350758da7f69SStefano Zampini     }
350858da7f69SStefano Zampini   } else {
350958da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
351058da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
351112edc857SStefano Zampini     }
351212edc857SStefano Zampini   }
3513674ae819SStefano Zampini   PetscFunctionReturn(0);
3514674ae819SStefano Zampini }
3515674ae819SStefano Zampini 
3516984c4197SStefano Zampini /* uncomment for testing purposes */
3517984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3518674ae819SStefano Zampini #undef __FUNCT__
3519674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3520674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3521674ae819SStefano Zampini {
3522674ae819SStefano Zampini   PetscErrorCode    ierr;
3523674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3524674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3525674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3526984c4197SStefano Zampini   /* one and zero */
3527984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3528984c4197SStefano Zampini   /* space to store constraints and their local indices */
35299162d606SStefano Zampini   PetscScalar       *constraints_data;
35309162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
35319162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
35329162d606SStefano Zampini   PetscInt          *constraints_n;
3533984c4197SStefano Zampini   /* iterators */
3534b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3535984c4197SStefano Zampini   /* BLAS integers */
3536e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3537e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3538c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3539727cdba6SStefano Zampini   /* reuse */
35400e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
35410e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3542984c4197SStefano Zampini   /* change of basis */
3543b3d85658SStefano Zampini   PetscBool         qr_needed;
35449162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3545984c4197SStefano Zampini   /* auxiliary stuff */
354664efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
35478a0068c3SStefano Zampini   PetscInt          ncc;
3548984c4197SStefano Zampini   /* some quantities */
354945a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3550a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3551984c4197SStefano Zampini 
3552674ae819SStefano Zampini   PetscFunctionBegin;
35538e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
35548e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
35558e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
355616909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
3557088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3558088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
35590e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
35600e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
35610e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
35620e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
35630e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3564088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3565cf5a6209SStefano Zampini 
3566cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
35679162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3568cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3569cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3570cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3571cf5a6209SStefano Zampini     PetscScalar  *array;
3572cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3573cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3574674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3575b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3576674ae819SStefano Zampini     PetscScalar  *work;
3577674ae819SStefano Zampini     PetscReal    *singular_vals;
3578674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3579674ae819SStefano Zampini     PetscReal    *rwork;
3580674ae819SStefano Zampini #endif
3581674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3582674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3583674ae819SStefano Zampini #else
3584964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3585964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3586674ae819SStefano Zampini #endif
3587674ae819SStefano Zampini 
3588674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3589d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3590e4d548c7SStefano Zampini     /* print some info */
35911f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
3592e4d548c7SStefano Zampini       PetscInt nv;
3593e4d548c7SStefano Zampini 
3594e4d548c7SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
3595e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
3596e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3597e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3598e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3599e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
3600e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
3601e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3602e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3603e4d548c7SStefano Zampini     }
3604e4d548c7SStefano Zampini 
3605d06fc5fdSStefano Zampini     /* free unneeded index sets */
3606d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3607d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3608674ae819SStefano Zampini     }
3609d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3610d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3611d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3612d06fc5fdSStefano Zampini       }
3613d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3614d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3615d06fc5fdSStefano Zampini     }
3616d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3617d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3618d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3619d06fc5fdSStefano Zampini       }
3620d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3621d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3622d06fc5fdSStefano Zampini     }
362370022509SStefano Zampini 
3624674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3625674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3626674ae819SStefano Zampini     if (nearnullsp) {
3627674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3628f4ddd8eeSStefano Zampini       /* remove any stored info */
3629f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3630f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3631f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3632f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3633f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3634473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3635f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3636f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3637f4ddd8eeSStefano Zampini       }
3638984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3639984c4197SStefano Zampini       nnsp_size = 0;
3640674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3641674ae819SStefano Zampini     }
3642984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3643984c4197SStefano Zampini     max_constraints = nnsp_size;
3644984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3645984c4197SStefano Zampini 
3646674ae819SStefano Zampini     /*
3647674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
36489162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
36499162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
36509162d606SStefano Zampini          There can be multiple constraints per connected component
3651674ae819SStefano Zampini                                                                                                                                                            */
3652674ae819SStefano Zampini     n_vertices = 0;
3653674ae819SStefano Zampini     if (ISForVertices) {
3654674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3655674ae819SStefano Zampini     }
36569162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
36579162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
36589162d606SStefano Zampini 
36599162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
36609162d606SStefano Zampini     total_counts *= max_constraints;
3661674ae819SStefano Zampini     total_counts += n_vertices;
36624641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
36639162d606SStefano Zampini 
3664674ae819SStefano Zampini     total_counts = 0;
3665674ae819SStefano Zampini     max_size_of_constraint = 0;
3666674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
36679162d606SStefano Zampini       IS used_is;
3668674ae819SStefano Zampini       if (i<n_ISForEdges) {
36699162d606SStefano Zampini         used_is = ISForEdges[i];
3670674ae819SStefano Zampini       } else {
36719162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3672674ae819SStefano Zampini       }
36739162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3674674ae819SStefano Zampini       total_counts += j;
3675674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3676674ae819SStefano Zampini     }
36779162d606SStefano 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);
36789162d606SStefano Zampini 
3679984c4197SStefano Zampini     /* get local part of global near null space vectors */
3680785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3681984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3682984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3683e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3684e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3685984c4197SStefano Zampini     }
3686674ae819SStefano Zampini 
3687242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3688242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3689a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3690242a89d7SStefano Zampini 
3691984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3692a773dcb8SStefano Zampini     if (!skip_lapack) {
3693674ae819SStefano Zampini       PetscScalar temp_work;
3694911cabfeSStefano Zampini 
3695674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3696984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3697785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3698785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3699785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3700674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3701785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3702674ae819SStefano Zampini #endif
3703674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3704c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3705c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3706674ae819SStefano Zampini       lwork = -1;
3707674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3708674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3709c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3710674ae819SStefano Zampini #else
3711c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3712674ae819SStefano Zampini #endif
3713674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3714984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3715674ae819SStefano Zampini #else /* on missing GESVD */
3716674ae819SStefano Zampini       /* SVD */
3717674ae819SStefano Zampini       PetscInt max_n,min_n;
3718674ae819SStefano Zampini       max_n = max_size_of_constraint;
3719984c4197SStefano Zampini       min_n = max_constraints;
3720984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3721674ae819SStefano Zampini         min_n = max_size_of_constraint;
3722984c4197SStefano Zampini         max_n = max_constraints;
3723674ae819SStefano Zampini       }
3724785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3725674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3726785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3727674ae819SStefano Zampini #endif
3728674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3729674ae819SStefano Zampini       lwork = -1;
3730e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3731e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3732b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3733674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3734674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
37359162d606SStefano 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));
3736674ae819SStefano Zampini #else
37379162d606SStefano 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));
3738674ae819SStefano Zampini #endif
3739674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3740984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3741984c4197SStefano Zampini #endif /* on missing GESVD */
3742674ae819SStefano Zampini       /* Allocate optimal workspace */
3743674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3744854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3745674ae819SStefano Zampini     }
3746674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3747674ae819SStefano Zampini     total_counts = 0;
37489162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
37499162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3750674ae819SStefano Zampini     /* vertices */
37519162d606SStefano Zampini     if (n_vertices) {
3752674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
37539162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3754674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
37559162d606SStefano Zampini         constraints_n[total_counts] = 1;
37569162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
37579162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
37589162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3759674ae819SStefano Zampini         total_counts++;
3760674ae819SStefano Zampini       }
3761674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3762674ae819SStefano Zampini       n_vertices = total_counts;
3763674ae819SStefano Zampini     }
3764984c4197SStefano Zampini 
3765674ae819SStefano Zampini     /* edges and faces */
37669162d606SStefano Zampini     total_counts_cc = total_counts;
3767911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
37689162d606SStefano Zampini       IS        used_is;
37699162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
37709162d606SStefano Zampini 
3771911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
37729162d606SStefano Zampini         used_is = ISForEdges[ncc];
3773984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3774674ae819SStefano Zampini       } else {
37759162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3776984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3777674ae819SStefano Zampini       }
3778674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
37799162d606SStefano Zampini 
37809162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
37819162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3782984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3783984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3784674ae819SStefano Zampini       if (nnsp_has_cnst) {
37855b08dc53SStefano Zampini         PetscScalar quad_value;
37869162d606SStefano Zampini 
37879162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
37889162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
37899162d606SStefano Zampini 
3790a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3791674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3792a773dcb8SStefano Zampini         } else {
3793a773dcb8SStefano Zampini           quad_value = 1.0;
3794a773dcb8SStefano Zampini         }
3795674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
37969162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3797674ae819SStefano Zampini         }
37989162d606SStefano Zampini         temp_constraints++;
3799674ae819SStefano Zampini         total_counts++;
3800674ae819SStefano Zampini       }
3801674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3802984c4197SStefano Zampini         PetscReal real_value;
38039162d606SStefano Zampini         PetscScalar *ptr_to_data;
38049162d606SStefano Zampini 
3805984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
38069162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3807674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
38089162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3809674ae819SStefano Zampini         }
3810984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3811984c4197SStefano Zampini         /* check if array is null on the connected component */
3812e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
38139162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
38145b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3815674ae819SStefano Zampini           temp_constraints++;
3816674ae819SStefano Zampini           total_counts++;
38179162d606SStefano Zampini           if (!idxs_copied) {
38189162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
38199162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3820674ae819SStefano Zampini           }
3821674ae819SStefano Zampini         }
38229162d606SStefano Zampini       }
38239162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
382445a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3825eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3826a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
38279162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
38289162d606SStefano Zampini 
38299162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3830a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
38319162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3832a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
38339162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3834a773dcb8SStefano Zampini         } else { /* perform SVD */
3835984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
38369162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3837674ae819SStefano Zampini 
3838674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3839984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3840984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3841984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3842984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3843984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3844984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3845984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3846984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3847674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3848e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3849984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3850674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3851674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
38529162d606SStefano 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));
3853674ae819SStefano Zampini             }
3854674ae819SStefano Zampini           }
3855e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3856e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3857e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3858674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3859c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3860674ae819SStefano Zampini #else
3861c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3862674ae819SStefano Zampini #endif
3863674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3864984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3865984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3866674ae819SStefano Zampini           j = 0;
3867984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3868674ae819SStefano Zampini           total_counts = total_counts-j;
386945a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3870e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3871c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3872c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3873c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3874c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3875c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3876c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3877674ae819SStefano Zampini           if (j<temp_constraints) {
3878984c4197SStefano Zampini             PetscInt ii;
3879984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3880674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38819162d606SStefano 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));
3882674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3883984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3884674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
38859162d606SStefano 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];
3886674ae819SStefano Zampini               }
3887674ae819SStefano Zampini             }
3888674ae819SStefano Zampini           }
3889674ae819SStefano Zampini #else  /* on missing GESVD */
3890e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3891e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3892b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3893674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3894674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
38959162d606SStefano 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));
3896674ae819SStefano Zampini #else
38979162d606SStefano 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));
3898674ae819SStefano Zampini #endif
3899984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3900674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3901984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3902e310c8b4SStefano Zampini           k = temp_constraints;
3903e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3904674ae819SStefano Zampini           j = 0;
3905e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
390645a1bb75SStefano Zampini           valid_constraints = k-j;
3907911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3908984c4197SStefano Zampini #endif /* on missing GESVD */
3909674ae819SStefano Zampini         }
3910a773dcb8SStefano Zampini       }
39119162d606SStefano Zampini       /* update pointers information */
39129162d606SStefano Zampini       if (valid_constraints) {
39139162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
39149162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
39159162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
39169162d606SStefano Zampini         /* set change_of_basis flag */
391745a1bb75SStefano Zampini         if (boolforchange) {
3918b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
39199162d606SStefano Zampini         }
3920b3d85658SStefano Zampini         total_counts_cc++;
392145a1bb75SStefano Zampini       }
392245a1bb75SStefano Zampini     }
3923984c4197SStefano Zampini     /* free workspace */
39248f1c130eSStefano Zampini     if (!skip_lapack) {
3925984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3926984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3927984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3928984c4197SStefano Zampini #endif
3929984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3930984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3931984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3932984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3933984c4197SStefano Zampini #endif
3934984c4197SStefano Zampini     }
3935984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3936984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3937984c4197SStefano Zampini     }
3938984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3939cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3940cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3941cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3942cf5a6209SStefano Zampini     }
3943cf5a6209SStefano Zampini     if (n_ISForFaces) {
3944cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3945cf5a6209SStefano Zampini     }
3946cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3947cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3948cf5a6209SStefano Zampini     }
3949cf5a6209SStefano Zampini     if (n_ISForEdges) {
3950cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3951cf5a6209SStefano Zampini     }
3952cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
395308122e43SStefano Zampini   } else {
395408122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3955984c4197SStefano Zampini 
395608122e43SStefano Zampini     total_counts = 0;
395708122e43SStefano Zampini     n_vertices = 0;
3958d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3959d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
396008122e43SStefano Zampini     }
396108122e43SStefano Zampini     max_constraints = 0;
39629162d606SStefano Zampini     total_counts_cc = 0;
396308122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
396408122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
39659162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
396608122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
396708122e43SStefano Zampini     }
39689162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
39699162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
39709162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
39719162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
397274d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
39739162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
39749162d606SStefano Zampini     total_counts_cc = 0;
39759162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
39769162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
39779162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
397808122e43SStefano Zampini       }
397908122e43SStefano Zampini     }
39809162d606SStefano Zampini #if 0
39819162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
39829162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
39839162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
39849162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
39859162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
39869162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
39879162d606SStefano Zampini       }
39889162d606SStefano Zampini       printf("\n");
39899162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
39909162d606SStefano Zampini     }
39911b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
39928bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
39931b968477SStefano Zampini     }
39941b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
39958bec7fa6SStefano 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]);
39961b968477SStefano Zampini     }
399708122e43SStefano Zampini #endif
399808122e43SStefano Zampini 
39998bec7fa6SStefano Zampini     max_size_of_constraint = 0;
40009162d606SStefano 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]);
40019162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
400208122e43SStefano Zampini     /* Change of basis */
4003b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
400408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
400508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
400608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
4007b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
400808122e43SStefano Zampini         }
400908122e43SStefano Zampini       }
401008122e43SStefano Zampini     }
401108122e43SStefano Zampini   }
4012984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
40134f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
401408122e43SStefano Zampini 
40159162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
40169162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
40176c4ed002SBarry 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);
4018674ae819SStefano Zampini 
4019674ae819SStefano Zampini   /* Create constraint matrix */
4020674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
402116f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
4022984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
4023984c4197SStefano Zampini 
4024984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
4025a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
4026a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
402774d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
4028984c4197SStefano Zampini   total_primal_vertices=0;
4029b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
40309162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
40319162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
403272b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
40339162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
4034b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
403564efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
40369162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
40379162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
4038a717540cSStefano Zampini       }
4039b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
404091af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
4041a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
4042a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
4043a717540cSStefano Zampini       }
4044fa434743SStefano Zampini     } else {
4045b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
4046fa434743SStefano Zampini     }
4047a717540cSStefano Zampini   }
4048b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
4049b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
4050674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
405170022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4052b3d85658SStefano Zampini 
40534f1b2e48SStefano 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);
40540e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
40550e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
4056984c4197SStefano Zampini 
4057984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
405874d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
4059785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
4060984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
406174d5cdf7SStefano Zampini 
4062984c4197SStefano Zampini   j = total_primal_vertices;
406374d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
4064b3d85658SStefano Zampini   cum = total_primal_vertices;
40659162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
40664641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
4067b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
4068b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
4069b3d85658SStefano Zampini       cum++;
40709162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
407174d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
407274d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
407374d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
407474d5cdf7SStefano Zampini       }
40759162d606SStefano Zampini       j += constraints_n[i];
4076674ae819SStefano Zampini     }
4077674ae819SStefano Zampini   }
4078674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
4079674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
4080088faed8SStefano Zampini 
4081674ae819SStefano Zampini   /* set values in constraint matrix */
4082984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
40830e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4084674ae819SStefano Zampini   }
4085984c4197SStefano Zampini   total_counts = total_primal_vertices;
40869162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
40874641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
40889162d606SStefano Zampini       PetscInt *cols;
40899162d606SStefano Zampini 
40909162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
40919162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
40929162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
40939162d606SStefano Zampini         PetscInt    row = total_counts+k;
40949162d606SStefano Zampini         PetscScalar *vals;
40959162d606SStefano Zampini 
40969162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
40979162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
40989162d606SStefano Zampini       }
40999162d606SStefano Zampini       total_counts += constraints_n[i];
4100674ae819SStefano Zampini     }
4101674ae819SStefano Zampini   }
4102674ae819SStefano Zampini   /* assembling */
4103674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4104674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4105088faed8SStefano Zampini 
4106984c4197SStefano Zampini   /*
41076a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4108984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
4109f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
4110984c4197SStefano Zampini   */
4111674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
4112674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
4113026de310SStefano Zampini     /* dual and primal dofs on a single cc */
4114984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
4115984c4197SStefano Zampini     /* working stuff for GEQRF */
411681d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
4117984c4197SStefano Zampini     PetscBLASInt lqr_work;
4118984c4197SStefano Zampini     /* working stuff for UNGQR */
4119984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
4120984c4197SStefano Zampini     PetscBLASInt lgqr_work;
4121984c4197SStefano Zampini     /* working stuff for TRTRS */
4122984c4197SStefano Zampini     PetscScalar  *trs_rhs;
41233f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
4124984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
4125984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
4126984c4197SStefano Zampini     PetscScalar  *start_vals;
4127984c4197SStefano Zampini     /* working stuff for values insertion */
41284641a718SStefano Zampini     PetscBT      is_primal;
412964efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
4130906d46d4SStefano Zampini     /* matrix sizes */
4131906d46d4SStefano Zampini     PetscInt     global_size,local_size;
4132906d46d4SStefano Zampini     /* temporary change of basis */
4133906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
4134cf5a6209SStefano Zampini     /* extra space for debugging */
4135cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
4136984c4197SStefano Zampini 
4137906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
4138906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
413916f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
4140bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
4141906d46d4SStefano Zampini     /* nonzeros for local mat */
4142bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
41431dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4144bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
41451dd7afcfSStefano Zampini     } else {
41461dd7afcfSStefano Zampini       const PetscInt *ii;
41471dd7afcfSStefano Zampini       PetscInt       n;
41481dd7afcfSStefano Zampini       PetscBool      flg_row;
41491dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
41501dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
41511dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
41521dd7afcfSStefano Zampini     }
41539162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
4154a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
41559162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
4156a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
41579162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
4158a717540cSStefano Zampini         } else {
41599162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
41609162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
4161a717540cSStefano Zampini         }
4162a717540cSStefano Zampini       }
4163a717540cSStefano Zampini     }
4164906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
4165bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
41661dd7afcfSStefano Zampini     /* Set interior change in the matrix */
41671dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4168bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
4169906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
4170a717540cSStefano Zampini       }
41711dd7afcfSStefano Zampini     } else {
41721dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
41731dd7afcfSStefano Zampini       PetscScalar    *aa;
41741dd7afcfSStefano Zampini       PetscInt       n;
41751dd7afcfSStefano Zampini       PetscBool      flg_row;
41761dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
41771dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
41781dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
41791dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
41801dd7afcfSStefano Zampini       }
41811dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
41821dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
41831dd7afcfSStefano Zampini     }
4184a717540cSStefano Zampini 
4185a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
4186a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4187a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4188a717540cSStefano Zampini     }
4189a717540cSStefano Zampini 
4190a717540cSStefano Zampini 
4191a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
4192a717540cSStefano Zampini     /*
4193a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
4194a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
4195a717540cSStefano Zampini 
4196a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
4197a717540cSStefano Zampini 
4198a6b551f4SStefano 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)
4199a6b551f4SStefano Zampini 
4200a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
4201a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
4202a717540cSStefano Zampini             |              ...                        |
4203a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
4204a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
4205a717540cSStefano Zampini 
4206a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
4207a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
4208a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
4209a6b551f4SStefano Zampini 
4210a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
4211a717540cSStefano Zampini     */
4212a717540cSStefano Zampini     if (qr_needed) {
4213984c4197SStefano Zampini       /* space to store Q */
4214854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
4215984c4197SStefano Zampini       /* first we issue queries for optimal work */
42163f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
42173f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
42183f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4219984c4197SStefano Zampini       lqr_work = -1;
42203f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
4221984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
4222984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
4223785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
4224984c4197SStefano Zampini       lgqr_work = -1;
42253f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
42263f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
42273f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
42283f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
42293f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
42303f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
4231984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
4232984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
4233785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
4234984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
4235785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
4236984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
4237785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
4238a717540cSStefano Zampini       /* allocating workspace for check */
4239a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
4240cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
4241a717540cSStefano Zampini       }
4242a717540cSStefano Zampini     }
4243984c4197SStefano Zampini     /* array to store whether a node is primal or not */
42444641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
4245473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
42460e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
42476c4ed002SBarry 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);
424839e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
424939e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
425039e2fb2aSStefano Zampini     }
425139e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
4252984c4197SStefano Zampini 
4253a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
42549162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
42559162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
42564641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
4257984c4197SStefano Zampini         /* get constraint info */
42589162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
4259984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
4260984c4197SStefano Zampini 
4261984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
42629162d606SStefano 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);
4263674ae819SStefano Zampini         }
4264984c4197SStefano Zampini 
4265fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
4266a717540cSStefano Zampini 
4267a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
4268a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
42699162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4270a717540cSStefano Zampini           }
4271984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
42729162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4273984c4197SStefano Zampini 
4274984c4197SStefano Zampini           /* compute QR decomposition of constraints */
42753f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42763f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42773f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4278674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42793f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
4280984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
4281674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4282984c4197SStefano Zampini 
4283984c4197SStefano Zampini           /* explictly compute R^-T */
4284984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
4285984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
42863f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42873f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
42883f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
42893f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
4290984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42913f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
4292984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
4293984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4294984c4197SStefano Zampini 
4295a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
42963f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42973f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
42983f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
42993f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4300984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43013f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
4302984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
4303984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4304984c4197SStefano Zampini 
4305984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
4306984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
4307984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
43083f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
43093f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
43103f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
43113f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43123f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
43133f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4314984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43159162d606SStefano 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));
4316984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
43179162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4318984c4197SStefano Zampini 
4319984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
43209162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
4321984c4197SStefano Zampini           /* insert cols for primal dofs */
4322984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
4323984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
43249162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4325906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4326984c4197SStefano Zampini           }
4327984c4197SStefano Zampini           /* insert cols for dual dofs */
4328984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
43299162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
4330984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
43319162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4332906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4333984c4197SStefano Zampini               j++;
4334674ae819SStefano Zampini             }
4335674ae819SStefano Zampini           }
4336984c4197SStefano Zampini 
4337984c4197SStefano Zampini           /* check change of basis */
4338984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
4339984c4197SStefano Zampini             PetscInt   ii,jj;
4340984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
4341c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
4342c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4343c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
4344c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4345c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
4346c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
4347984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4348cf5a6209SStefano 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));
4349984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4350984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
4351984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
4352cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
4353cf5a6209SStefano 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;
4354674ae819SStefano Zampini               }
4355674ae819SStefano Zampini             }
4356984c4197SStefano Zampini             if (!valid_qr) {
435722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
4358984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
4359984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
4360cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
4361cf5a6209SStefano 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]));
4362674ae819SStefano Zampini                   }
4363cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
4364cf5a6209SStefano 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]));
4365984c4197SStefano Zampini                   }
4366984c4197SStefano Zampini                 }
4367984c4197SStefano Zampini               }
4368674ae819SStefano Zampini             } else {
436922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
4370674ae819SStefano Zampini             }
4371674ae819SStefano Zampini           }
4372a717540cSStefano Zampini         } else { /* simple transformation block */
4373a717540cSStefano Zampini           PetscInt    row,col;
4374a6b551f4SStefano Zampini           PetscScalar val,norm;
4375a6b551f4SStefano Zampini 
4376a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
43779162d606SStefano 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));
4378a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
43799162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
43809162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4381bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
43829162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
4383906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
43849162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
4385a717540cSStefano Zampini             } else {
4386a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
43879162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4388a717540cSStefano Zampini                 if (row != col) {
43899162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
4390a717540cSStefano Zampini                 } else {
43919162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
4392a717540cSStefano Zampini                 }
4393906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
4394a717540cSStefano Zampini               }
4395a717540cSStefano Zampini             }
4396a717540cSStefano Zampini           }
439798a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
439822d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4399a717540cSStefano Zampini           }
4400674ae819SStefano Zampini         }
4401984c4197SStefano Zampini       } else {
4402984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
44039162d606SStefano 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);
4404674ae819SStefano Zampini         }
4405674ae819SStefano Zampini       }
4406674ae819SStefano Zampini     }
4407a717540cSStefano Zampini 
4408a717540cSStefano Zampini     /* free workspace */
4409a717540cSStefano Zampini     if (qr_needed) {
4410984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4411cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4412984c4197SStefano Zampini       }
4413984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4414984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4415984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4416984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4417984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4418674ae819SStefano Zampini     }
4419a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4420906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4421906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4422906d46d4SStefano Zampini 
4423906d46d4SStefano Zampini     /* assembling of global change of variable */
442488c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
4425bbb9e6c6SStefano Zampini       Mat      tmat;
442616f15bc4SStefano Zampini       PetscInt bs;
442716f15bc4SStefano Zampini 
4428906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4429906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4430bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4431bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4432bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4433bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
443416f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
443516f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4436906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4437bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4438bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4439bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4440bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4441bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4442e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4443e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4444bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4445bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
444688c03ad3SStefano Zampini 
4447906d46d4SStefano Zampini       /* check */
4448906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
4449906d46d4SStefano Zampini         PetscReal error;
4450906d46d4SStefano Zampini         Vec       x,x_change;
4451906d46d4SStefano Zampini 
4452906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4453906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4454906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4455906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4456e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4457e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4458bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4459e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4460e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4461906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4462906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4463906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4464906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4465bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4466906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
4467906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4468906d46d4SStefano Zampini       }
4469b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
4470b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
4471b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4472bf3a8328SStefano Zampini 
4473bf3a8328SStefano Zampini         if (pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined) {
4474bf3a8328SStefano Zampini           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints");CHKERRQ(ierr);
4475bf3a8328SStefano Zampini         }
4476b96c3477SStefano Zampini         if (sub_schurs->S_Ej_all) {
4477ac632422SStefano Zampini           Mat                    S_new,tmat;
4478bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
4479bbb9e6c6SStefano Zampini 
4480bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
44816816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4482bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4483bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
4484bf3a8328SStefano Zampini             IS                     is_V;
4485b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4486b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4487b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4488b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4489b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4490bf3a8328SStefano Zampini           }
4491bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4492ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4493b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4494ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4495bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4496bf3a8328SStefano Zampini             const PetscScalar *array;
4497bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
4498bf3a8328SStefano Zampini             PetscInt          i,n_V;
4499bf3a8328SStefano Zampini 
4500b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4501b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4502b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4503b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4504b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4505b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
4506b087196eSStefano Zampini               PetscScalar val;
4507b087196eSStefano Zampini               PetscInt    idx;
4508b087196eSStefano Zampini 
4509b087196eSStefano Zampini               idx = idxs_V[i];
4510b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
4511b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4512b087196eSStefano Zampini             }
4513b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4514b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4515bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4516bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4517bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4518bf3a8328SStefano Zampini           }
4519ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
4520ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4521ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
4522ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4523b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4524ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4525bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
4526b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4527bf3a8328SStefano Zampini             }
4528ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
4529ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4530ac632422SStefano Zampini           }
4531b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
453288c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4533b96c3477SStefano Zampini         }
4534c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
4535c9db6a07SStefano Zampini         if (sub_schurs->change) {
4536c9db6a07SStefano Zampini           PetscInt i;
4537c9db6a07SStefano Zampini 
4538c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
4539c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
4540c9db6a07SStefano Zampini           }
4541c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
4542c9db6a07SStefano Zampini         }
4543b96c3477SStefano Zampini       }
454416909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
454516909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
454616909a7fSStefano Zampini       } else {
4547906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
454816909a7fSStefano Zampini       }
45491dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
455027b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
455172b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
455272b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
455372b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
455472b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
455572b8c272SStefano Zampini     }
45561dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
455727b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
4558b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4559b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4560906d46d4SStefano Zampini     } else {
45611dd7afcfSStefano Zampini       Mat benign_global = NULL;
456227b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
45631dd7afcfSStefano Zampini         Mat tmat;
45641dd7afcfSStefano Zampini 
45651dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
45661dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
45671dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
45681dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
45691dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
45701dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
45711dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
45721dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
45731dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
45741dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
45751dd7afcfSStefano Zampini           Mat M;
45761dd7afcfSStefano Zampini 
45771dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
45781dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
45791dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
45801dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
4581906d46d4SStefano Zampini         } else {
45821dd7afcfSStefano Zampini           Mat         eye;
45831dd7afcfSStefano Zampini           PetscScalar *array;
45841dd7afcfSStefano Zampini 
45851dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
45861dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
45871dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
45881dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
4589906d46d4SStefano Zampini           }
45901dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
45911dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45921dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45931dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
45941dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
45951dd7afcfSStefano Zampini         }
45961dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
45971dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
45981dd7afcfSStefano Zampini       }
45991dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
46001dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
46011dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
460227b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
46031dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
46041dd7afcfSStefano Zampini       }
46051dd7afcfSStefano Zampini     }
460616909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
460716909a7fSStefano Zampini       IS             is_global;
460816909a7fSStefano Zampini       const PetscInt *gidxs;
460916909a7fSStefano Zampini 
461016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
461116909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
461216909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
461316909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
461416909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
461516909a7fSStefano Zampini     }
46161dd7afcfSStefano Zampini   }
46171dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
46181dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
4619b9b85e73SStefano Zampini   }
4620a717540cSStefano Zampini 
462172b8c272SStefano Zampini   if (!pcbddc->fake_change) {
46224f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
46234f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
46244f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
46254f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4626019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4627019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
4628019a44ceSStefano Zampini       pcbddc->local_primal_size++;
4629019a44ceSStefano Zampini     }
4630019a44ceSStefano Zampini 
4631019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
4632727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
4633727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
46349f47a83aSStefano 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);
4635c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
46360e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
46379f47a83aSStefano 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);
4638727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4639727cdba6SStefano Zampini       }
46400e6343abSStefano Zampini     }
4641727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4642b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
464372b8c272SStefano Zampini   }
464472b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4645727cdba6SStefano Zampini 
4646a717540cSStefano Zampini   /* flush dbg viewer */
4647b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4648b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4649b8ffe317SStefano Zampini   }
4650a717540cSStefano Zampini 
4651e310c8b4SStefano Zampini   /* free workspace */
4652a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
46534641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
465408122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
46559162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
46569162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
465708122e43SStefano Zampini   } else {
46589162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
46599162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
46609162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
466108122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
466208122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
46639162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
46649162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
466508122e43SStefano Zampini   }
4666674ae819SStefano Zampini   PetscFunctionReturn(0);
4667674ae819SStefano Zampini }
4668674ae819SStefano Zampini 
4669674ae819SStefano Zampini #undef __FUNCT__
4670674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4671674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4672674ae819SStefano Zampini {
4673674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4674674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4675674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
467614f95afaSStefano Zampini   PetscInt    ierr,i,N;
4677674ae819SStefano Zampini 
4678674ae819SStefano Zampini   PetscFunctionBegin;
46798e61c736SStefano Zampini   /* Reset previously computed graph */
46808e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4681674ae819SStefano Zampini   /* Init local Graph struct */
46827fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
46833bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4684674ae819SStefano Zampini 
4685575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
46865099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
46875099eff2SStefano 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);
4688575ad6abSStefano Zampini   }
46899577ea80SStefano Zampini 
4690674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4691d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
46924d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
46934d379d7bSStefano Zampini     PetscInt  nvtxs;
4694e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4695674ae819SStefano Zampini 
46962fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
46972fffb893SStefano Zampini     if (flg_row) {
46984d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4699b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
47002fffb893SStefano Zampini     }
47012fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4702674ae819SStefano Zampini   }
47039b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
47049b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4705674ae819SStefano Zampini   }
4706674ae819SStefano Zampini 
4707674ae819SStefano Zampini   /* Setup of Graph */
470814f95afaSStefano 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);
4709674ae819SStefano Zampini 
47104f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
47114f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
47124f1b2e48SStefano Zampini     PetscInt *local_subs;
47134f1b2e48SStefano Zampini 
47144f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
47154f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
47164f1b2e48SStefano Zampini       const PetscInt *idxs;
47174f1b2e48SStefano Zampini       PetscInt       nl,j;
47184f1b2e48SStefano Zampini 
47194f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
47204f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
47214f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
47224f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
47234f1b2e48SStefano Zampini       }
47244f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
47254f1b2e48SStefano Zampini     }
47264f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
47274f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
47284f1b2e48SStefano Zampini   }
47294f1b2e48SStefano Zampini 
4730674ae819SStefano Zampini   /* Graph's connected components analysis */
4731674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4732674ae819SStefano Zampini   PetscFunctionReturn(0);
4733674ae819SStefano Zampini }
4734674ae819SStefano Zampini 
4735dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4736674ae819SStefano Zampini #undef __FUNCT__
4737674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4738dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4739674ae819SStefano Zampini {
4740dc456d91SStefano Zampini   PetscSF        sf;
4741dc456d91SStefano Zampini   PetscLayout    map;
4742dc456d91SStefano Zampini   const PetscInt *idxs;
4743dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4744dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4745dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4746dc456d91SStefano Zampini   PetscMPIInt    commsize;
4747674ae819SStefano Zampini   PetscBool      first_found;
4748674ae819SStefano Zampini   PetscErrorCode ierr;
4749674ae819SStefano Zampini 
4750674ae819SStefano Zampini   PetscFunctionBegin;
4751dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4752dc456d91SStefano Zampini   if (subset_mult) {
4753dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4754dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4755dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4756674ae819SStefano Zampini   }
4757dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4758dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4759dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4760dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4761dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4762dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4763674ae819SStefano Zampini   }
4764dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4765b2566f29SBarry Smith   ierr = MPIU_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4766dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4767dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4768dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4769dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4770dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4771dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4772dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4773dc456d91SStefano Zampini 
4774dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4775dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4776dc456d91SStefano Zampini   if (subset_mult) {
4777dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4778dc456d91SStefano Zampini 
4779dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4780dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4781dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4782674ae819SStefano Zampini   } else {
4783dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4784674ae819SStefano Zampini   }
4785dc456d91SStefano Zampini   /* local size of new subset */
4786dc456d91SStefano Zampini   n_n = 0;
4787dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4788dc456d91SStefano Zampini 
4789dc456d91SStefano Zampini   /* global indexes in layout */
4790dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4791dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4792dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4793dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4794dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4795dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4796dc456d91SStefano Zampini 
4797dc456d91SStefano Zampini   /* reduce from leaves to roots */
4798dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
479964a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
480064a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4801dc456d91SStefano Zampini 
4802dc456d91SStefano Zampini   /* count indexes in local part of layout */
4803674ae819SStefano Zampini   nlocals = 0;
4804674ae819SStefano Zampini   first_index = -1;
4805674ae819SStefano Zampini   first_found = PETSC_FALSE;
4806dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4807dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4808674ae819SStefano Zampini       first_found = PETSC_TRUE;
4809674ae819SStefano Zampini       first_index = i;
4810674ae819SStefano Zampini     }
4811dc456d91SStefano Zampini     nlocals += root_data[i];
4812674ae819SStefano Zampini   }
4813dc456d91SStefano Zampini 
4814dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
48155fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4816dc456d91SStefano Zampini   start = 0;
481764a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
48185fa240b1SStefano Zampini #else
481964a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
48205fa240b1SStefano Zampini   start = start-nlocals;
48215fa240b1SStefano Zampini #endif
48225fa240b1SStefano Zampini 
4823dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4824dc456d91SStefano Zampini     *N_n = start + nlocals;
4825dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4826dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4827674ae819SStefano Zampini   }
48285fa240b1SStefano Zampini 
48295fa240b1SStefano Zampini   /* adapt root data with cumulative */
4830674ae819SStefano Zampini   if (first_found) {
4831dc456d91SStefano Zampini     PetscInt old_index;
4832dc456d91SStefano Zampini 
4833dc456d91SStefano Zampini     root_data[first_index] += start;
4834674ae819SStefano Zampini     old_index = first_index;
4835dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4836dc456d91SStefano Zampini       if (root_data[i]) {
4837dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4838674ae819SStefano Zampini         old_index = i;
4839674ae819SStefano Zampini       }
4840674ae819SStefano Zampini     }
4841674ae819SStefano Zampini   }
4842dc456d91SStefano Zampini 
4843dc456d91SStefano Zampini   /* from roots to leaves */
4844dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4845dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4846dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4847dc456d91SStefano Zampini 
4848dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4849dc456d91SStefano Zampini   if (subset_mult) {
4850dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4851dc456d91SStefano Zampini     PetscInt        cum;
4852dc456d91SStefano Zampini 
4853dc456d91SStefano Zampini     cum = 0;
4854dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4855dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4856dc456d91SStefano Zampini       PetscInt j;
4857dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4858674ae819SStefano Zampini     }
4859dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4860674ae819SStefano Zampini   } else {
4861dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4862dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4863674ae819SStefano Zampini     }
4864674ae819SStefano Zampini   }
4865dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4866dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4867674ae819SStefano Zampini   PetscFunctionReturn(0);
4868674ae819SStefano Zampini }
48699a7d3425SStefano Zampini 
48709a7d3425SStefano Zampini #undef __FUNCT__
48719a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
48729a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
48739a7d3425SStefano Zampini {
48749a7d3425SStefano Zampini   PetscInt       i,j;
48759a7d3425SStefano Zampini   PetscScalar    *alphas;
48769a7d3425SStefano Zampini   PetscErrorCode ierr;
48779a7d3425SStefano Zampini 
48789a7d3425SStefano Zampini   PetscFunctionBegin;
48799a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4880785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
48819a7d3425SStefano Zampini   for (i=0;i<n;i++) {
48829a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
48839a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
48849a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
48859a7d3425SStefano Zampini   }
48869a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
48879a7d3425SStefano Zampini   PetscFunctionReturn(0);
48889a7d3425SStefano Zampini }
48899a7d3425SStefano Zampini 
4890e7931f94SStefano Zampini #undef __FUNCT__
489170cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
489257de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
4893e7931f94SStefano Zampini {
489457de7509SStefano Zampini   Mat            A;
4895e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4896e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
489752e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
489852e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
489927b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
490057de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
490127b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
490227b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
490327b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
490427b6a85dSStefano Zampini   MPI_Comm       subcomm;
490552e5ac9dSStefano Zampini   PetscErrorCode ierr;
4906a57a6d2fSStefano Zampini 
4907e7931f94SStefano Zampini   PetscFunctionBegin;
490857de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
490957de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
491057de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
491157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
491257de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
491357de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
491457de7509SStefano Zampini 
491557de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
491657de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
491757de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
491857de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
491957de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
492057de7509SStefano Zampini   im_active = !!(n);
492157de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
492257de7509SStefano Zampini   void_procs = size - active_procs;
492357de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
492457de7509SStefano Zampini   if (void_procs) {
492557de7509SStefano Zampini     PetscInt ncand;
492657de7509SStefano Zampini 
492757de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
492857de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
492957de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
493057de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
493157de7509SStefano Zampini       if (!procs_candidates[i]) {
493257de7509SStefano Zampini         procs_candidates[ncand++] = i;
493357de7509SStefano Zampini       }
493457de7509SStefano Zampini     }
493557de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
493657de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
493757de7509SStefano Zampini   }
493857de7509SStefano Zampini 
493957de7509SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix */
494057de7509SStefano Zampini   if (active_procs < *n_subdomains) {
494157de7509SStefano Zampini     PetscInt issize,isidx;
494257de7509SStefano Zampini     if (im_active) {
494357de7509SStefano Zampini       issize = 1;
494457de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
494557de7509SStefano Zampini         isidx = procs_candidates[rank];
494657de7509SStefano Zampini       } else {
494757de7509SStefano Zampini         isidx = rank;
494857de7509SStefano Zampini       }
494957de7509SStefano Zampini     } else {
495057de7509SStefano Zampini       issize = 0;
495157de7509SStefano Zampini       isidx = -1;
495257de7509SStefano Zampini     }
495357de7509SStefano Zampini     *n_subdomains = active_procs;
495457de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
4955daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
495657de7509SStefano Zampini     PetscFunctionReturn(0);
495757de7509SStefano Zampini   }
4958c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
4959c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
496027b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
4961e7931f94SStefano Zampini 
4962e7931f94SStefano Zampini   /* Get info on mapping */
49633bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
49643bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4965e7931f94SStefano Zampini 
4966e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4967785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4968e7931f94SStefano Zampini   xadj[0] = 0;
4969e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4970785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4971785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
497227b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
497327b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
497427b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
497527b6a85dSStefano Zampini       count[shared[i][j]] += 1;
4976e7931f94SStefano Zampini 
497727b6a85dSStefano Zampini   xadj_count = 0;
49782b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
497927b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
498027b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
4981d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4982d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4983d023bfaeSStefano Zampini         xadj_count++;
498427b6a85dSStefano Zampini         break;
498527b6a85dSStefano Zampini       }
4986e7931f94SStefano Zampini     }
4987e7931f94SStefano Zampini   }
4988d023bfaeSStefano Zampini   xadj[1] = xadj_count;
498927b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
49903bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4991e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4992e7931f94SStefano Zampini 
49933837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4994e7931f94SStefano Zampini 
499527b6a85dSStefano Zampini   /* Restrict work on active processes only */
499627b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
499727b6a85dSStefano Zampini   if (void_procs) {
499827b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
499927b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
500027b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
500127b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
500227b6a85dSStefano Zampini   } else {
500327b6a85dSStefano Zampini     psubcomm = NULL;
500427b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
500527b6a85dSStefano Zampini   }
500627b6a85dSStefano Zampini 
500727b6a85dSStefano Zampini   v_wgt = NULL;
500827b6a85dSStefano Zampini   if (!color) {
5009e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
5010e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
5011e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5012c8587f34SStefano Zampini   } else {
501352e5ac9dSStefano Zampini     Mat             subdomain_adj;
501452e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
501552e5ac9dSStefano Zampini     MatPartitioning partitioner;
501627b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
501752e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
501857de7509SStefano Zampini     PetscMPIInt     size;
5019b0c7d250SStefano Zampini     PetscBool       aggregate;
5020b0c7d250SStefano Zampini 
502127b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
502227b6a85dSStefano Zampini     if (void_procs) {
502327b6a85dSStefano Zampini       PetscInt prank = rank;
5024785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
502527b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
5026e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
5027e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
5028c8587f34SStefano Zampini       }
5029e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
503027b6a85dSStefano Zampini     } else {
503127b6a85dSStefano Zampini       oldranks = NULL;
503227b6a85dSStefano Zampini     }
5033b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
503427b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
5035b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
5036b0c7d250SStefano Zampini       PetscMPIInt nrank;
5037b0c7d250SStefano Zampini       PetscScalar *vals;
5038b0c7d250SStefano Zampini 
503927b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
5040b0c7d250SStefano Zampini       lrows = 0;
5041b0c7d250SStefano Zampini       if (nrank<redprocs) {
5042b0c7d250SStefano Zampini         lrows = size/redprocs;
5043b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
5044b0c7d250SStefano Zampini       }
504527b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
5046b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
5047b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5048b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5049b0c7d250SStefano Zampini       row = nrank;
5050b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
5051b0c7d250SStefano Zampini       cols = adjncy;
5052b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
5053b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5054b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5055b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5056b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
505752e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
505852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
505952e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5060b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
506127b6a85dSStefano Zampini       if (use_vwgt) {
506227b6a85dSStefano Zampini         Vec               v;
506327b6a85dSStefano Zampini         const PetscScalar *array;
506427b6a85dSStefano Zampini         PetscInt          nl;
506527b6a85dSStefano Zampini 
506627b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
506727b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
506827b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
506927b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
507027b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
507127b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
507227b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
507322db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
507427b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
507527b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
507627b6a85dSStefano Zampini       }
5077b0c7d250SStefano Zampini     } else {
507827b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
507927b6a85dSStefano Zampini       if (use_vwgt) {
508027b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
508127b6a85dSStefano Zampini         v_wgt[0] = local_size;
508227b6a85dSStefano Zampini       }
5083b0c7d250SStefano Zampini     }
508422b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5085e7931f94SStefano Zampini 
5086e7931f94SStefano Zampini     /* Partition */
508727b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5088e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
508927b6a85dSStefano Zampini     if (v_wgt) {
5090e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5091c8587f34SStefano Zampini     }
509257de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
509357de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5094e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5095e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
509622b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5097e7931f94SStefano Zampini 
509852e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
509952e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
510052e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
510152e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
510257de7509SStefano Zampini     if (!aggregate) {
510357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
510427b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
510527b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
510627b6a85dSStefano Zampini #endif
510757de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
510827b6a85dSStefano Zampini       } else if (oldranks) {
5109b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
511027b6a85dSStefano Zampini       } else {
511127b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
511257de7509SStefano Zampini       }
511328143c3dSStefano Zampini     } else {
5114b0c7d250SStefano Zampini       PetscInt    idxs[1];
5115b0c7d250SStefano Zampini       PetscMPIInt tag;
5116b0c7d250SStefano Zampini       MPI_Request *reqs;
5117b0c7d250SStefano Zampini 
5118b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5119b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5120b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
512127b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
512228143c3dSStefano Zampini       }
512327b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5124b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5125b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
512657de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
512727b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
512827b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
512927b6a85dSStefano Zampini #endif
513057de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
513127b6a85dSStefano Zampini       } else if (oldranks) {
5132b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
513327b6a85dSStefano Zampini       } else {
513427b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5135e7931f94SStefano Zampini       }
513657de7509SStefano Zampini     }
513752e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5138e7931f94SStefano Zampini     /* clean up */
5139e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
514052e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5141e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5142e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5143e7931f94SStefano Zampini   }
514427b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
514557de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5146e7931f94SStefano Zampini 
5147e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5148e7931f94SStefano Zampini   i = 1;
514927b6a85dSStefano Zampini   if (!color) i=0;
515057de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5151e7931f94SStefano Zampini   PetscFunctionReturn(0);
5152e7931f94SStefano Zampini }
5153e7931f94SStefano Zampini 
5154e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5155e7931f94SStefano Zampini 
5156e7931f94SStefano Zampini #undef __FUNCT__
5157e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
515857de7509SStefano 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[])
5159e7931f94SStefano Zampini {
516070cf5478SStefano Zampini   Mat                    local_mat;
5161e7931f94SStefano Zampini   IS                     is_sends_internal;
51629d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
516328143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
51649d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
5165e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
5166e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
5167e7931f94SStefano Zampini   const PetscInt*        is_indices;
5168e7931f94SStefano Zampini   MatType                new_local_type;
5169e7931f94SStefano Zampini   /* buffers */
5170e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
517128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
51729d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
5173e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
5174e7931f94SStefano Zampini   /* MPI */
517528143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
517628143c3dSStefano Zampini   PetscSubcomm           subcomm;
5177e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
517828143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
517928143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
518028143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
518128143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
518228143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
5183e7931f94SStefano Zampini   PetscErrorCode         ierr;
5184e7931f94SStefano Zampini 
5185e7931f94SStefano Zampini   PetscFunctionBegin;
518657de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5187e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
518828143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
518957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
519057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
519157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
519257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
519357de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
519457de7509SStefano Zampini 
519557de7509SStefano Zampini   /* further checks */
5196e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5197e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5198e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
5199e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
5200e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
520157de7509SStefano Zampini   if (reuse && *mat_n) {
520270cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
520357de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
520470cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
520528143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
520670cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
520770cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
520870cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
520970cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
521070cf5478SStefano Zampini   }
5211e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
5212e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
521357de7509SStefano Zampini 
5214e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
5215e7931f94SStefano Zampini   if (!is_sends) {
521628143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
521757de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
5218c8587f34SStefano Zampini   } else {
5219e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
5220e7931f94SStefano Zampini     is_sends_internal = is_sends;
5221c8587f34SStefano Zampini   }
5222e7931f94SStefano Zampini 
5223e7931f94SStefano Zampini   /* get comm */
5224a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
5225e7931f94SStefano Zampini 
5226e7931f94SStefano Zampini   /* compute number of sends */
5227e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
5228e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
5229e7931f94SStefano Zampini 
5230e7931f94SStefano Zampini   /* compute number of receives */
5231e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
5232785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
5233e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
5234e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5235e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
5236e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
5237e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
5238e7931f94SStefano Zampini 
523928143c3dSStefano Zampini   /* restrict comm if requested */
524028143c3dSStefano Zampini   subcomm = 0;
524128143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
524228143c3dSStefano Zampini   if (restrict_comm) {
5243779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
5244779c1cceSStefano Zampini 
524528143c3dSStefano Zampini     color = 0;
524653a05cb3SStefano Zampini     if (restrict_full) {
524753a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
524853a05cb3SStefano Zampini     } else {
524953a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
525053a05cb3SStefano Zampini     }
5251b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
525228143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
525328143c3dSStefano Zampini     /* check if reuse has been requested */
525457de7509SStefano Zampini     if (reuse) {
525528143c3dSStefano Zampini       if (*mat_n) {
525628143c3dSStefano Zampini         PetscMPIInt subcommsize2;
525728143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
525828143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
525928143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
526028143c3dSStefano Zampini       } else {
526128143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
526228143c3dSStefano Zampini       }
526328143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
5264779c1cceSStefano Zampini       PetscMPIInt rank;
5265779c1cceSStefano Zampini 
5266779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
526728143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
526828143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
526928143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
5270306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
527128143c3dSStefano Zampini     }
527228143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
527328143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
527428143c3dSStefano Zampini   } else {
527528143c3dSStefano Zampini     comm_n = comm;
527628143c3dSStefano Zampini   }
527728143c3dSStefano Zampini 
5278e7931f94SStefano Zampini   /* prepare send/receive buffers */
5279785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
5280e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
5281785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
5282e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
528328143c3dSStefano Zampini   if (nis) {
5284854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
528528143c3dSStefano Zampini   }
5286e7931f94SStefano Zampini 
528728143c3dSStefano Zampini   /* Get data from local matrices */
52886c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
5289e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
5290e7931f94SStefano Zampini     /*
5291e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
5292e7931f94SStefano Zampini        send_buffer_idxs should contain:
5293e7931f94SStefano Zampini        - MatType_PRIVATE type
5294e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
5295e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
5296e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
5297e7931f94SStefano Zampini     */
52986c4ed002SBarry Smith   else {
5299e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
53003bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
5301854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
5302e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
5303e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
53043bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5305e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
53063bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5307e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
5308e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
5309e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
5310e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
5311c8587f34SStefano Zampini     }
5312c8587f34SStefano Zampini   }
5313e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
531428143c3dSStefano Zampini   /* additional is (if any) */
531528143c3dSStefano Zampini   if (nis) {
531628143c3dSStefano Zampini     PetscMPIInt psum;
531728143c3dSStefano Zampini     PetscInt j;
531828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
531928143c3dSStefano Zampini       PetscInt plen;
532028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
532128143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
532228143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
532328143c3dSStefano Zampini     }
5324854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
532528143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
532628143c3dSStefano Zampini       PetscInt plen;
532728143c3dSStefano Zampini       const PetscInt *is_array_idxs;
532828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
532928143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
533028143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
533128143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
533228143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
533328143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
533428143c3dSStefano Zampini     }
533528143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
533628143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
533728143c3dSStefano Zampini     }
533828143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
533928143c3dSStefano Zampini   }
534028143c3dSStefano Zampini 
5341e7931f94SStefano Zampini   buf_size_idxs = 0;
5342e7931f94SStefano Zampini   buf_size_vals = 0;
534328143c3dSStefano Zampini   buf_size_idxs_is = 0;
5344e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5345e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
5346e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
534728143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
5348e7931f94SStefano Zampini   }
5349785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
5350785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
535195ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
5352e7931f94SStefano Zampini 
5353e7931f94SStefano Zampini   /* get new tags for clean communications */
5354e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
5355e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
535628143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
5357e7931f94SStefano Zampini 
5358e7931f94SStefano Zampini   /* allocate for requests */
5359785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
5360785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
536195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
5362785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
5363785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
536495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
5365e7931f94SStefano Zampini 
5366e7931f94SStefano Zampini   /* communications */
5367e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
5368e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
536928143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
5370e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5371e7931f94SStefano Zampini     source_dest = onodes[i];
5372e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
5373e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
5374e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5375e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
537628143c3dSStefano Zampini     if (nis) {
537757de7509SStefano Zampini       source_dest = onodes_is[i];
537828143c3dSStefano 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);
537928143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
538028143c3dSStefano Zampini     }
5381e7931f94SStefano Zampini   }
5382e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
5383e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
5384e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
5385e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
538628143c3dSStefano Zampini     if (nis) {
538728143c3dSStefano 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);
538828143c3dSStefano Zampini     }
5389e7931f94SStefano Zampini   }
5390e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5391e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
5392e7931f94SStefano Zampini 
5393e7931f94SStefano Zampini   /* assemble new l2g map */
5394e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5395e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
53969d30be91SStefano Zampini   new_local_rows = 0;
5397e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
53989d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5399e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5400e7931f94SStefano Zampini   }
54019d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
5402e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
54039d30be91SStefano Zampini   new_local_rows = 0;
5404e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
54059d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
54069d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5407e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5408e7931f94SStefano Zampini   }
54099d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
54109d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
5411e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
5412e7931f94SStefano Zampini 
5413e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
5414e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
5415e7931f94SStefano 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) */
5416e7931f94SStefano Zampini   if (n_recvs) {
541728143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
5418e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
5419e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
5420e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
5421e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
5422e7931f94SStefano Zampini         break;
5423e7931f94SStefano Zampini       }
5424e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
5425e7931f94SStefano Zampini     }
5426e7931f94SStefano Zampini     switch (new_local_type_private) {
542728143c3dSStefano Zampini       case MATDENSE_PRIVATE:
542828143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
5429e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
5430e7931f94SStefano Zampini           bs = 1;
543128143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
543228143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
543328143c3dSStefano Zampini           bs = 1;
543428143c3dSStefano Zampini         }
5435e7931f94SStefano Zampini         break;
5436e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
5437e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
5438e7931f94SStefano Zampini         bs = 1;
5439e7931f94SStefano Zampini         break;
5440e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
5441e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
5442e7931f94SStefano Zampini         break;
5443e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
5444e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
5445e7931f94SStefano Zampini         break;
5446e7931f94SStefano Zampini       default:
54479d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
5448e7931f94SStefano Zampini         break;
5449e7931f94SStefano Zampini     }
545028143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
545128143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
545228143c3dSStefano Zampini     bs = 1;
5453e7931f94SStefano Zampini   }
5454e7931f94SStefano Zampini 
545570cf5478SStefano Zampini   /* create MATIS object if needed */
545657de7509SStefano Zampini   if (!reuse) {
5457e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
5458e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
545970cf5478SStefano Zampini   } else {
546070cf5478SStefano Zampini     /* it also destroys the local matrices */
546157de7509SStefano Zampini     if (*mat_n) {
546270cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
546357de7509SStefano Zampini     } else { /* this is a fake object */
546457de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
546557de7509SStefano Zampini     }
546670cf5478SStefano Zampini   }
546770cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
5468e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
54699d30be91SStefano Zampini 
54709d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
54719d30be91SStefano Zampini 
54729d30be91SStefano Zampini   /* Global to local map of received indices */
54739d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
54749d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
54759d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
54769d30be91SStefano Zampini 
54779d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
54789d30be91SStefano Zampini   buf_size_idxs = 0;
54799d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
54809d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
54819d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
54829d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
54839d30be91SStefano Zampini   }
54849d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
54859d30be91SStefano Zampini 
54869d30be91SStefano Zampini   /* set preallocation */
54879d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
54889d30be91SStefano Zampini   if (!newisdense) {
54899d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
54909d30be91SStefano Zampini 
54919d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
54929d30be91SStefano Zampini     if (n_recvs) {
54939d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
54949d30be91SStefano Zampini     }
54959d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
54969d30be91SStefano Zampini       PetscInt j;
54979d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
54989d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
54999d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
55009d30be91SStefano Zampini         }
55019d30be91SStefano Zampini       } else {
55029d30be91SStefano Zampini         /* TODO */
55039d30be91SStefano Zampini       }
55049d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
55059d30be91SStefano Zampini     }
55069d30be91SStefano Zampini     if (new_local_nnz) {
55079d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
55089d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
55099d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
55109d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
55119d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
55129d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
55139d30be91SStefano Zampini     } else {
55149d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
55159d30be91SStefano Zampini     }
55169d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
55179d30be91SStefano Zampini   } else {
55189d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
55199d30be91SStefano Zampini   }
5520e7931f94SStefano Zampini 
5521e7931f94SStefano Zampini   /* set values */
5522e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
55239d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5524e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5525e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5526e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
55279d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5528e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5529e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5530e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
553128143c3dSStefano Zampini     } else {
553228143c3dSStefano Zampini       /* TODO */
5533e7931f94SStefano Zampini     }
5534e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5535e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5536e7931f94SStefano Zampini   }
5537e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5538e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
553970cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
554070cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55419d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
55429d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5543e7931f94SStefano Zampini 
5544dfd14d43SStefano Zampini #if 0
554528143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5546e7931f94SStefano Zampini     Vec       lvec,rvec;
5547e7931f94SStefano Zampini     PetscReal infty_error;
5548e7931f94SStefano Zampini 
55492a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5550e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5551e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5552e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
555370cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5554e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5555e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5556e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5557e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5558e7931f94SStefano Zampini   }
555928143c3dSStefano Zampini #endif
5560e7931f94SStefano Zampini 
556128143c3dSStefano Zampini   /* assemble new additional is (if any) */
556228143c3dSStefano Zampini   if (nis) {
556328143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
556428143c3dSStefano Zampini 
556528143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5566854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
556728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
556828143c3dSStefano Zampini     psum = 0;
556928143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
557028143c3dSStefano Zampini       for (j=0;j<nis;j++) {
557128143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
557228143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
557328143c3dSStefano Zampini         psum += plen;
557428143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
557528143c3dSStefano Zampini       }
557628143c3dSStefano Zampini     }
5577854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5578854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
557928143c3dSStefano Zampini     for (i=1;i<nis;i++) {
558028143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
558128143c3dSStefano Zampini     }
558228143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
558328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
558428143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
558528143c3dSStefano Zampini       for (j=0;j<nis;j++) {
558628143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
558728143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
558828143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
558928143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
559028143c3dSStefano Zampini       }
559128143c3dSStefano Zampini     }
559228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
559328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
559428143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
559528143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
559628143c3dSStefano Zampini     }
559728143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
559828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
559928143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
560028143c3dSStefano Zampini   }
5601e7931f94SStefano Zampini   /* free workspace */
560228143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5603e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5604e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5605e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5606e7931f94SStefano Zampini   if (isdense) {
5607e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5608e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5609e7931f94SStefano Zampini   } else {
5610e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5611e7931f94SStefano Zampini   }
561228143c3dSStefano Zampini   if (nis) {
561328143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
561428143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
561528143c3dSStefano Zampini   }
5616e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5617e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
561828143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5619e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5620e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
562128143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5622e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5623e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5624e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5625e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5626e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
562728143c3dSStefano Zampini   if (nis) {
562828143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
562928143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
563028143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
563128143c3dSStefano Zampini   }
563228143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
563328143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
563428143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
563528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
563628143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
563728143c3dSStefano Zampini     }
563853a05cb3SStefano Zampini     *mat_n = NULL;
563928143c3dSStefano Zampini   }
5640e7931f94SStefano Zampini   PetscFunctionReturn(0);
5641e7931f94SStefano Zampini }
5642a57a6d2fSStefano Zampini 
564312edc857SStefano Zampini /* temporary hack into ksp private data structure */
5644af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
564512edc857SStefano Zampini 
5646c8587f34SStefano Zampini #undef __FUNCT__
5647c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5648c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5649c8587f34SStefano Zampini {
5650c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5651c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
565220a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
56539881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
565420a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
56556e683305SStefano Zampini   IS                     coarse_is,*isarray;
56566e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
565730368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5658f9eb5b7dSStefano Zampini   PC                     pc_temp;
5659c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5660c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5661f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
56624f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
56636e683305SStefano Zampini   Mat                    t_coarse_mat_is;
566457de7509SStefano Zampini   PetscInt               ncoarse;
566568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
566622bc73bbSStefano Zampini   PetscScalar            *array;
566757de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
566857de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
56699881197aSStefano Zampini   PetscErrorCode         ierr;
5670fdc09c96SStefano Zampini 
5671c8587f34SStefano Zampini   PetscFunctionBegin;
5672c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
567368457ee5SStefano 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 */
5674fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
56755a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5676fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5677f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5678f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5679f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5680fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
568151bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
568251bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5683dc4bcba2SStefano Zampini         PC        pc;
5684dc4bcba2SStefano Zampini         PetscBool isbddc;
5685dc4bcba2SStefano Zampini 
5686dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5687dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5688dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5689dc4bcba2SStefano Zampini         if (isbddc) {
569063c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
569163c961adSStefano Zampini         } else {
5692727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
569363c961adSStefano Zampini         }
5694fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5695fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5696fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5697f4ddd8eeSStefano Zampini       }
5698fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5699fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5700f4ddd8eeSStefano Zampini     }
570170cf5478SStefano Zampini     /* reset any subassembling information */
570257de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
570370cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
570457de7509SStefano Zampini     }
57056e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5706fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5707f4ddd8eeSStefano Zampini   }
570857de7509SStefano Zampini   /* assemble coarse matrix */
570957de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
571057de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
571157de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
571257de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
571318a45a71SStefano Zampini   } else {
571457de7509SStefano Zampini     coarse_mat = NULL;
571557de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
57166e683305SStefano Zampini   }
5717e7931f94SStefano Zampini 
5718abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5719abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5720abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5721abbbba34SStefano Zampini 
5722abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
572322bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
572422bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
572522bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
572622bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5727e176bc59SStefano 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);
57286e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
57296e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57306e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5731abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5732abbbba34SStefano Zampini 
573357de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
573457de7509SStefano Zampini   im_active = !!(pcis->n);
573557de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
573657de7509SStefano Zampini 
573757de7509SStefano Zampini   /* determine number of process partecipating to coarse solver and compute subassembling pattern */
573857de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
573957de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
574057de7509SStefano Zampini   coarse_mat_is = NULL;
574157de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
574257de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
574357de7509SStefano Zampini   full_restr = PETSC_TRUE;
574457de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(pcbddc->coarse_size,pcbddc->coarse_eqs_per_proc);
574557de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
574657de7509SStefano Zampini   if (multilevel_requested) {
574757de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
574857de7509SStefano Zampini     restr = PETSC_FALSE;
574957de7509SStefano Zampini     full_restr = PETSC_FALSE;
575057de7509SStefano Zampini   } else {
575157de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
575257de7509SStefano Zampini     restr = PETSC_TRUE;
575357de7509SStefano Zampini     full_restr = PETSC_TRUE;
575457de7509SStefano Zampini   }
575557de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
575657de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
575757de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
575857de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
575957de7509SStefano Zampini     PetscInt    psum;
576057de7509SStefano Zampini     PetscMPIInt size;
576157de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
576257de7509SStefano Zampini     else psum = 0;
576357de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
576457de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
576557de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
576657de7509SStefano Zampini   }
576757de7509SStefano Zampini   /* determine if we can go multilevel */
576857de7509SStefano Zampini   if (multilevel_requested) {
576957de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
577057de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
577157de7509SStefano Zampini   }
577257de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
577357de7509SStefano Zampini 
5774e4d548c7SStefano Zampini   /* dump subassembling pattern */
5775e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
5776e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
5777e4d548c7SStefano Zampini   }
5778e4d548c7SStefano Zampini 
57796e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
578027b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
57816e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
57826e683305SStefano Zampini     const PetscInt         *idxs;
57836e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
57846e683305SStefano Zampini 
57856e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
57860be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
57876e683305SStefano Zampini     /* allocate space for temporary storage */
5788854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5789854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
57906e683305SStefano Zampini     /* allocate for IS array */
57916e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
57926e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
579327b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
579430368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5795854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
57966e683305SStefano Zampini     /* dofs splitting */
57976e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
57986e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
57996e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
58006e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
58016e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
58026e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
58036e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
580430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
58056e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
58066e683305SStefano Zampini     }
58076e683305SStefano Zampini     /* neumann boundaries */
58086e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
58096e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
58106e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
58116e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
58126e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
58136e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
58146e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
581530368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
58166e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
58176e683305SStefano Zampini     }
58186e683305SStefano Zampini     /* free memory */
58196e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
58206e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
58216e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
58226e683305SStefano Zampini   } else {
58236e683305SStefano Zampini     nis = 0;
58246e683305SStefano Zampini     nisdofs = 0;
58256e683305SStefano Zampini     nisneu = 0;
582630368db7SStefano Zampini     nisvert = 0;
58276e683305SStefano Zampini     isarray = NULL;
58286e683305SStefano Zampini   }
58296e683305SStefano Zampini   /* destroy no longer needed map */
58306e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
58316e683305SStefano Zampini 
583257de7509SStefano Zampini   /* subassemble */
583357de7509SStefano Zampini   if (multilevel_allowed) {
583457de7509SStefano Zampini     PetscBool reuse,reuser;
583557de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
583657de7509SStefano Zampini     else reuse = PETSC_FALSE;
583757de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
583857de7509SStefano Zampini     if (reuser) {
583957de7509SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray);CHKERRQ(ierr);
584074e2c79eSStefano Zampini     } else {
584157de7509SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
584274e2c79eSStefano Zampini     }
58431f4df5f7SStefano 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 */
584474e2c79eSStefano Zampini   } else {
584557de7509SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
58466e683305SStefano Zampini   }
584757de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
584857de7509SStefano Zampini     PetscMPIInt size;
584957de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
585057de7509SStefano Zampini     if (!multilevel_allowed) {
585157de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
58526e683305SStefano Zampini     } else {
585357de7509SStefano Zampini       Mat A;
5854779c1cceSStefano Zampini 
585557de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
585657de7509SStefano Zampini       if (coarse_mat_is) {
585757de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
585857de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
585957de7509SStefano Zampini         coarse_mat = coarse_mat_is;
586057de7509SStefano Zampini       }
586157de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
586257de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
586357de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
5864779c1cceSStefano Zampini     }
5865779c1cceSStefano Zampini   }
586657de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
586757de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
58686e683305SStefano Zampini 
58696e683305SStefano Zampini   /* create local to global scatters for coarse problem */
587068457ee5SStefano Zampini   if (compute_vecs) {
58716e683305SStefano Zampini     PetscInt lrows;
58726e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
587357de7509SStefano Zampini     if (coarse_mat) {
587457de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
58756e683305SStefano Zampini     } else {
58766e683305SStefano Zampini       lrows = 0;
58776e683305SStefano Zampini     }
58786e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
58796e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
58806e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
58816e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
58826e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
58836e683305SStefano Zampini   }
58846e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
5885c8587f34SStefano Zampini 
5886f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5887f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5888f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5889f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5890f9eb5b7dSStefano Zampini   } else {
5891f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5892f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5893c8587f34SStefano Zampini   }
5894c8587f34SStefano Zampini 
58956e683305SStefano Zampini   /* print some info if requested */
58966e683305SStefano Zampini   if (pcbddc->dbg_flag) {
58976e683305SStefano Zampini     if (!multilevel_allowed) {
58986e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
58996e683305SStefano Zampini       if (multilevel_requested) {
59006e683305SStefano 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);
59016e683305SStefano Zampini       } else if (pcbddc->max_levels) {
59026e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
59036e683305SStefano Zampini       }
59046e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
59056e683305SStefano Zampini     }
59066e683305SStefano Zampini   }
59076e683305SStefano Zampini 
5908f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
590957de7509SStefano Zampini   if (coarse_mat) {
59106a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
59116e683305SStefano Zampini     if (pcbddc->dbg_flag) {
591257de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
59136e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
59146e683305SStefano Zampini     }
5915f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5916312be037SStefano Zampini       char prefix[256],str_level[16];
5917e604994aSStefano Zampini       size_t len;
591857de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5919422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5920c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5921f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
592257de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5923c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
59246e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5925c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5926c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5927e604994aSStefano Zampini       /* prefix */
5928e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5929e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5930e604994aSStefano Zampini       if (!pcbddc->current_level) {
5931e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5932e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5933c8587f34SStefano Zampini       } else {
5934e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5935312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5936312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
593734d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5938312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5939e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5940e604994aSStefano Zampini       }
5941e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
59423e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
59433e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
59443e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
59453e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5946f9eb5b7dSStefano Zampini       /* allow user customization */
5947f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
59483e3c6dadSStefano Zampini     }
59493e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
595051bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
59513e3c6dadSStefano Zampini     if (nisdofs) {
59523e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
59533e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
59543e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
59553e3c6dadSStefano Zampini       }
59563e3c6dadSStefano Zampini     }
59573e3c6dadSStefano Zampini     if (nisneu) {
59583e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
59593e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5960312be037SStefano Zampini     }
596130368db7SStefano Zampini     if (nisvert) {
596230368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
596330368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
596430368db7SStefano Zampini     }
5965f9eb5b7dSStefano Zampini 
5966f9eb5b7dSStefano Zampini     /* get some info after set from options */
5967f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5968f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
59694f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
59706e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5971f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5972f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5973f9eb5b7dSStefano Zampini     }
597439f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
59754f3a063dSStefano Zampini     if (isredundant) {
59764f3a063dSStefano Zampini       KSP inner_ksp;
59774f3a063dSStefano Zampini       PC  inner_pc;
59784f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
59794f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
59804f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
59814f3a063dSStefano Zampini     }
5982f9eb5b7dSStefano Zampini 
598357de7509SStefano Zampini     /* parameters which miss an API */
598457de7509SStefano Zampini     if (isbddc) {
5985720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
5986720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
598757de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
598827b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
598927b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
599027b6a85dSStefano Zampini         pcbddc_coarse->benign_compute_nonetflux = PETSC_TRUE;
5991720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
599259e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
5993720d30f9SStefano Zampini       }
5994d4d8cf7bSStefano Zampini     }
59959881197aSStefano Zampini 
59963301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
59975a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
59983301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
59993301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
60003301b35fSStefano Zampini     }
60013301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
60023301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
60033301b35fSStefano Zampini     }
60043301b35fSStefano Zampini     if (pc->pmat->spd_set) {
60053301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
60063301b35fSStefano Zampini     }
600727b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
600827b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
600927b6a85dSStefano Zampini     }
60106e683305SStefano Zampini     /* set operators */
60115f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
60126e683305SStefano Zampini     if (pcbddc->dbg_flag) {
60136e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
60146e683305SStefano Zampini     }
60156e683305SStefano Zampini   }
60166e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
6017b1ecc7b1SStefano Zampini #if 0
6018b9b85e73SStefano Zampini   {
6019b9b85e73SStefano Zampini     PetscViewer viewer;
6020b9b85e73SStefano Zampini     char filename[256];
6021b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
6022b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
60236a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6024b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
6025f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
6026b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
6027b9b85e73SStefano Zampini   }
6028b9b85e73SStefano Zampini #endif
6029f9eb5b7dSStefano Zampini 
603098a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
603198a51de6SStefano Zampini     Vec crhs,csol;
603204708bb6SStefano Zampini 
6033f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
6034f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
6035f347579bSStefano Zampini     if (!csol) {
60362a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
6037f9eb5b7dSStefano Zampini     }
6038f347579bSStefano Zampini     if (!crhs) {
60392a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
6040f347579bSStefano Zampini     }
6041b0f5fe93SStefano Zampini   }
6042b0f5fe93SStefano Zampini 
6043b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
6044b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
6045b0f5fe93SStefano Zampini 
6046b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
60474f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
60484f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
60494f1b2e48SStefano Zampini     }
6050b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
6051b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
6052b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6053b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6054b0f5fe93SStefano Zampini     if (coarse_mat) {
6055b0f5fe93SStefano Zampini       Vec         nullv;
6056b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
6057b0f5fe93SStefano Zampini       PetscInt    nl;
6058b0f5fe93SStefano Zampini 
6059b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
6060b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
6061b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6062b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
6063b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
6064b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
6065b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6066b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
6067b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
6068b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
6069b0f5fe93SStefano Zampini     }
6070b0f5fe93SStefano Zampini   }
6071b0f5fe93SStefano Zampini 
6072b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
6073b0f5fe93SStefano Zampini     PetscBool ispreonly;
6074b0f5fe93SStefano Zampini 
6075b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
6076b0f5fe93SStefano Zampini       PetscBool isnull;
6077b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
6078bef83e63SStefano Zampini       if (isnull) {
6079b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
6080b0f5fe93SStefano Zampini       }
6081bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
6082b0f5fe93SStefano Zampini     }
6083b0f5fe93SStefano Zampini     /* setup coarse ksp */
6084b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
6085cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
6086cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
60876e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
6088c8587f34SStefano Zampini       KSP       check_ksp;
60892b510759SStefano Zampini       KSPType   check_ksp_type;
6090c8587f34SStefano Zampini       PC        check_pc;
60916e683305SStefano Zampini       Vec       check_vec,coarse_vec;
60926a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
60932b510759SStefano Zampini       PetscInt  its;
60946e683305SStefano Zampini       PetscBool compute_eigs;
60956e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
60966e683305SStefano Zampini       PetscInt  neigs;
60978e185a42SStefano Zampini       const char *prefix;
6098c8587f34SStefano Zampini 
60992b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
61006e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
6101422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
610223ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6103f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
6104e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
6105e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
6106e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
61072b510759SStefano Zampini       if (ispreonly) {
61082b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
61096e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
61102b510759SStefano Zampini       } else {
6111cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
61126e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
6113c8587f34SStefano Zampini       }
6114c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
61156e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
61166e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
61176e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
6118a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
6119a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
6120a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
6121a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
6122c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
6123c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
6124c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
6125c8587f34SStefano Zampini       /* create random vec */
61262701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
6127c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
61286e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
6129c8587f34SStefano Zampini       /* solve coarse problem */
61306e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
6131cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
61326e683305SStefano Zampini       if (compute_eigs) {
6133854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
6134854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
61356e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
61366e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
61376e683305SStefano Zampini         lambda_min = eigs_r[0];
61386e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
61392701bc32SStefano Zampini           if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
61402701bc32SStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
6141cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
6142cbcc2c2aSStefano Zampini           }
6143c8587f34SStefano Zampini         }
6144c8587f34SStefano Zampini       }
6145cbcc2c2aSStefano Zampini 
6146c8587f34SStefano Zampini       /* check coarse problem residual error */
61476e683305SStefano Zampini       if (pcbddc->dbg_flag) {
61486e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
61496e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
61506e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
6151c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
61526e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
61536e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
6154779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
61556e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
61566e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
61576e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
61586e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
6159b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
6160b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
6161b0f5fe93SStefano Zampini         }
61626e683305SStefano Zampini         if (compute_eigs) {
61636e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
6164deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
6165c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
61666e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
61676e683305SStefano 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);
61686e683305SStefano Zampini           for (i=0;i<neigs;i++) {
61696e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
6170c8587f34SStefano Zampini           }
61716e683305SStefano Zampini         }
61726e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
61736e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
61746e683305SStefano Zampini       }
6175e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
61762701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
6177c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
61786e683305SStefano Zampini       if (compute_eigs) {
61796e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
61806e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
6181c8587f34SStefano Zampini       }
61826e683305SStefano Zampini     }
61836e683305SStefano Zampini   }
6184bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6185cbcc2c2aSStefano Zampini   /* print additional info */
6186cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
61876e683305SStefano Zampini     /* waits until all processes reaches this point */
61886e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
6189cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
6190cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6191cbcc2c2aSStefano Zampini   }
6192cbcc2c2aSStefano Zampini 
61932b510759SStefano Zampini   /* free memory */
6194fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
6195c8587f34SStefano Zampini   PetscFunctionReturn(0);
6196c8587f34SStefano Zampini }
6197674ae819SStefano Zampini 
6198f34684f1SStefano Zampini #undef __FUNCT__
6199f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
6200f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
6201f34684f1SStefano Zampini {
6202f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6203f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
6204f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
6205dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
6206dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
620773be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
6208dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
6209f34684f1SStefano Zampini   PetscErrorCode ierr;
6210f34684f1SStefano Zampini 
6211f34684f1SStefano Zampini   PetscFunctionBegin;
6212f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
62136c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
6214dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
62153bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
6216dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6217dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
6218dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
6219dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
6220dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
6221dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
62226c4ed002SBarry 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);
6223dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
6224dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6225dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
6226dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6227dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6228f34684f1SStefano Zampini 
6229f34684f1SStefano Zampini   /* check numbering */
6230f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
6231019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
6232dc456d91SStefano Zampini     PetscInt    i;
6233b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
6234f34684f1SStefano Zampini 
6235f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6236f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
6237f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
62381575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6239019a44ceSStefano Zampini     /* counter */
6240019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6241019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6242019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6243019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6244019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6245019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6246f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
6247f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
6248727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6249f34684f1SStefano Zampini     }
6250f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6251f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6252f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6253e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6254e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6255e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6256e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6257f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6258019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6259f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6260019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
62612c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
626275c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
6263b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
62642c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
62652c66d082SStefano 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);
6266f34684f1SStefano Zampini       }
6267f34684f1SStefano Zampini     }
6268019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6269b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
6270f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6271f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6272f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
6273f34684f1SStefano Zampini     }
6274f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6275f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6276e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6277e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6278f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
6279f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
6280b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
6281ca8b9ea9SStefano Zampini       PetscInt *gidxs;
6282ca8b9ea9SStefano Zampini 
6283ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
62843bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
6285f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
6286f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6287f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6288f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
62894bc2dc4bSStefano 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);
6290f34684f1SStefano Zampini       }
6291f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6292ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
6293f34684f1SStefano Zampini     }
6294f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
62951575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6296302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
6297f34684f1SStefano Zampini   }
62988bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
6299f34684f1SStefano Zampini   /* get back data */
6300f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
6301f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
6302674ae819SStefano Zampini   PetscFunctionReturn(0);
6303674ae819SStefano Zampini }
6304674ae819SStefano Zampini 
6305e456f2a8SStefano Zampini #undef __FUNCT__
6306e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
6307a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
6308e456f2a8SStefano Zampini {
6309e456f2a8SStefano Zampini   IS             localis_t;
6310a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
6311e456f2a8SStefano Zampini   PetscScalar    *vals;
6312e456f2a8SStefano Zampini   PetscErrorCode ierr;
6313e456f2a8SStefano Zampini 
6314e456f2a8SStefano Zampini   PetscFunctionBegin;
6315a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
6316e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
6317854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
6318e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
6319e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6320a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
6321a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
63221035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
6323a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
63241035eff8SStefano Zampini   }
6325a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
6326e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6327e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
6328a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
6329a7dc3881SStefano Zampini   /* now compute set in local ordering */
6330a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6331a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6332a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6333a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
6334a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6335ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6336e456f2a8SStefano Zampini       lsize++;
6337e456f2a8SStefano Zampini     }
6338e456f2a8SStefano Zampini   }
6339854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
6340a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6341ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6342e456f2a8SStefano Zampini       idxs[lsize++] = i;
6343e456f2a8SStefano Zampini     }
6344e456f2a8SStefano Zampini   }
6345a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6346a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
6347e456f2a8SStefano Zampini   *localis = localis_t;
6348e456f2a8SStefano Zampini   PetscFunctionReturn(0);
6349e456f2a8SStefano Zampini }
6350906d46d4SStefano Zampini 
6351b96c3477SStefano Zampini #undef __FUNCT__
6352b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
635308122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6354b96c3477SStefano Zampini {
6355a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6356b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6357b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6358a64f4aa4SStefano Zampini   Mat                 S_j;
6359b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6360b96c3477SStefano Zampini   PetscBool           free_used_adj;
6361b96c3477SStefano Zampini   PetscErrorCode      ierr;
6362b96c3477SStefano Zampini 
6363b96c3477SStefano Zampini   PetscFunctionBegin;
6364b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6365b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
636608122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6367b96c3477SStefano Zampini     used_xadj = NULL;
6368b96c3477SStefano Zampini     used_adjncy = NULL;
6369b96c3477SStefano Zampini   } else {
637008122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
637108122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
637208122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
637308122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6374b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6375b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6376b96c3477SStefano Zampini     } else {
63772fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6378b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6379b96c3477SStefano Zampini       PetscInt       nvtxs;
6380b96c3477SStefano Zampini 
63812fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
63822fffb893SStefano Zampini       if (flg_row) {
6383b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6384b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6385b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6386b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
63872fffb893SStefano Zampini       } else {
63882fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
63892fffb893SStefano Zampini         used_xadj = NULL;
63902fffb893SStefano Zampini         used_adjncy = NULL;
63912fffb893SStefano Zampini       }
63922fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6393b96c3477SStefano Zampini     }
6394b96c3477SStefano Zampini   }
6395d5574798SStefano Zampini 
6396d5574798SStefano Zampini   /* setup sub_schurs data */
6397a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6398df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6399df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6400a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
640191af6908SStefano 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);
6402a64f4aa4SStefano Zampini   } else {
64036816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
6404b7ab4a40SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;;
6405a3df083aSStefano Zampini     PetscInt  benign_n;
640672b8c272SStefano Zampini     Mat       change = NULL;
64079d54b7f4SStefano Zampini     Vec       scaling = NULL;
640872b8c272SStefano Zampini     IS        change_primal = NULL;
6409a3df083aSStefano Zampini 
64105feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
64115feab87aSStefano Zampini       PetscInt n_vertices;
64125feab87aSStefano Zampini 
64135feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
64142034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
64155feab87aSStefano Zampini     }
641604708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
641704708bb6SStefano Zampini     if (!isseqaij) {
641804708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
641904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
642004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
642104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
642204708bb6SStefano Zampini       } else {
6423511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
642404708bb6SStefano Zampini       }
642504708bb6SStefano Zampini     }
6426a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6427a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6428ca92afb2SStefano Zampini     } else {
6429a3df083aSStefano Zampini       benign_n = 0;
6430ca92afb2SStefano Zampini     }
6431b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
6432b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
6433b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
643472b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
643522db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
6436b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
643722db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
6438b7ab4a40SStefano Zampini     }
6439b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
6440b7ab4a40SStefano 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 */
6441b7ab4a40SStefano Zampini     if (need_change) {
644288c03ad3SStefano Zampini       PC_IS   *pcisf;
644388c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
644488c03ad3SStefano Zampini       PC      pcf;
644588c03ad3SStefano Zampini 
6446e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
644788c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
644888c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
644988c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
645088c03ad3SStefano Zampini       /* hacks */
645188c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
645272b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
645372b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
645472b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
645572b8c272SStefano Zampini       pcisf->n = pcis->n;
645672b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
645788c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
645888c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
645988c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
646088c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
646188c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
646288c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
646372b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
646488c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
646588c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
646672b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
646772b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
646872b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
646972b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
647072b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
647188c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
647272b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
647388c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
647488c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
647588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
647688c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
647788c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
647888c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
647988c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
648088c03ad3SStefano Zampini     }
64819d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
648291af6908SStefano 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);
648372b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
648472b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
6485ca92afb2SStefano Zampini   }
6486d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6487b96c3477SStefano Zampini 
6488b96c3477SStefano Zampini   /* free adjacency */
6489b96c3477SStefano Zampini   if (free_used_adj) {
6490b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6491b96c3477SStefano Zampini   }
6492b96c3477SStefano Zampini   PetscFunctionReturn(0);
6493b96c3477SStefano Zampini }
6494b96c3477SStefano Zampini 
6495b96c3477SStefano Zampini #undef __FUNCT__
6496b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
649708122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6498b96c3477SStefano Zampini {
6499b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6500b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6501b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6502b96c3477SStefano Zampini   PCBDDCGraph         graph;
6503b96c3477SStefano Zampini   PetscErrorCode      ierr;
6504b96c3477SStefano Zampini 
6505b96c3477SStefano Zampini   PetscFunctionBegin;
6506b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
650708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
65083301b35fSStefano Zampini     IS       verticesIS,verticescomm;
65093301b35fSStefano Zampini     PetscInt vsize,*idxs;
6510b96c3477SStefano Zampini 
6511b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
65123301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
65133301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
65143301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
65153301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
65163301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6517b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
65187fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
6519441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
65203301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6521b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6522b96c3477SStefano Zampini   } else {
6523b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6524b96c3477SStefano Zampini   }
6525e4d548c7SStefano Zampini   /* print some info */
6526e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
6527e4d548c7SStefano Zampini     IS       vertices;
6528e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
6529e4d548c7SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6530e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
6531e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
6532e4d548c7SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
6533e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6534e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6535e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
6536e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
6537e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
6538e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6539e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6540e4d548c7SStefano Zampini   }
6541b96c3477SStefano Zampini 
6542b96c3477SStefano Zampini   /* sub_schurs init */
6543a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6544a64f4aa4SStefano Zampini 
6545b96c3477SStefano Zampini   /* free graph struct */
654608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6547b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6548b96c3477SStefano Zampini   }
6549b96c3477SStefano Zampini   PetscFunctionReturn(0);
6550b96c3477SStefano Zampini }
6551fa34dd3eSStefano Zampini 
6552fa34dd3eSStefano Zampini #undef __FUNCT__
6553fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6554fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6555fa34dd3eSStefano Zampini {
6556fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6557fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6558fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6559fa34dd3eSStefano Zampini 
6560fa34dd3eSStefano Zampini   PetscFunctionBegin;
6561fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6562fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
65634f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6564fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
65654f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
656675c01103SStefano Zampini     PetscReal      norm;
6567fa34dd3eSStefano Zampini     PetscInt       i;
6568fa34dd3eSStefano Zampini 
6569fa34dd3eSStefano Zampini     /* B0 and B0_B */
6570fa34dd3eSStefano Zampini     if (zerodiag) {
6571fa34dd3eSStefano Zampini       IS       dummy;
6572fa34dd3eSStefano Zampini 
65734f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
65744f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6575fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6576fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6577fa34dd3eSStefano Zampini     }
6578fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6579fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6580fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6581fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6582fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6583fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6584fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6585fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6586fa34dd3eSStefano Zampini     /* S_j */
6587fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6588fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6589fa34dd3eSStefano Zampini 
6590fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6591fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6592fa34dd3eSStefano Zampini     /* continuous in primal space */
6593fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6594fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6595fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6596fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
65974f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
65984f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6599fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6600fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6601fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6602fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6603fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6604fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6605fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6606fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6607fa34dd3eSStefano Zampini 
6608fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6609fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6610fa34dd3eSStefano Zampini     /* local with Schur */
6611fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6612fa34dd3eSStefano Zampini     if (zerodiag) {
6613fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
66144f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6615fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6616fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6617fa34dd3eSStefano Zampini     }
6618fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6619fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6620fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6621fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6622fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6623fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6624fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6625fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6626fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6627fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6628fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6629fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6630fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6631fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6632fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6633fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6634fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6635fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6636fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6637fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6638fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6639fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6640fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6641fa34dd3eSStefano Zampini     if (zerodiag) {
6642fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6643fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
66444f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6645fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6646fa34dd3eSStefano Zampini     }
6647fa34dd3eSStefano Zampini     /* BDDC */
6648fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6649fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6650fa34dd3eSStefano Zampini 
6651fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6652fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6653fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6654fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
66554f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
66564f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6657fa34dd3eSStefano Zampini     }
66584f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6659fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6660fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6661fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6662fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6663fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6664fa34dd3eSStefano Zampini   }
6665fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6666fa34dd3eSStefano Zampini }
6667