xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision b334f2440e805fa741b9afc81bd144bdb37f1a77)
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 {
331f4df5f7SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
341f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
351f4df5f7SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
361f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
371f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
381f4df5f7SStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
391f4df5f7SStefano Zampini       }
401f4df5f7SStefano Zampini     }
411f4df5f7SStefano Zampini   }
421f4df5f7SStefano Zampini 
431f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
441f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
451f4df5f7SStefano Zampini   }
461f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
471f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
481f4df5f7SStefano Zampini   }
491f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
501f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
511f4df5f7SStefano Zampini   }
521f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
531f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
541f4df5f7SStefano Zampini   PetscFunctionReturn(0);
551f4df5f7SStefano Zampini }
561f4df5f7SStefano Zampini 
571f4df5f7SStefano Zampini #undef __FUNCT__
583e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
593e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
603e589ea0SStefano Zampini {
613e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
623e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
633e589ea0SStefano Zampini   PetscErrorCode    ierr;
643e589ea0SStefano Zampini 
653e589ea0SStefano Zampini   PetscFunctionBegin;
663e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
673e589ea0SStefano Zampini     PetscFunctionReturn(0);
683e589ea0SStefano Zampini   }
693e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
703e589ea0SStefano Zampini     Vec swap;
713e589ea0SStefano Zampini 
723e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
733e589ea0SStefano Zampini     swap = pcbddc->work_change;
743e589ea0SStefano Zampini     pcbddc->work_change = r;
753e589ea0SStefano Zampini     r = swap;
763e589ea0SStefano Zampini   }
773e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
783e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
793e589ea0SStefano Zampini   if (pcbddc->benign_n) {
803e589ea0SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
813e589ea0SStefano Zampini   } else {
823e589ea0SStefano Zampini     ierr = VecSet(pcis->vec2_D,0.);CHKERRQ(ierr);
833e589ea0SStefano Zampini   }
843e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
853e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
863e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
873e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
883e589ea0SStefano Zampini     Vec swap;
893e589ea0SStefano Zampini 
903e589ea0SStefano Zampini     swap = r;
913e589ea0SStefano Zampini     r = pcbddc->work_change;
923e589ea0SStefano Zampini     pcbddc->work_change = swap;
933e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
943e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
953e589ea0SStefano Zampini   }
963e589ea0SStefano Zampini   PetscFunctionReturn(0);
973e589ea0SStefano Zampini }
983e589ea0SStefano Zampini 
993e589ea0SStefano Zampini #undef __FUNCT__
100a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
101a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
102a3df083aSStefano Zampini {
103a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
104a3df083aSStefano Zampini   PetscErrorCode          ierr;
105a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
106a3df083aSStefano Zampini 
107a3df083aSStefano Zampini   PetscFunctionBegin;
108a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
109a3df083aSStefano Zampini   if (transpose) {
110a3df083aSStefano Zampini     apply_right = ctx->apply_left;
111a3df083aSStefano Zampini     apply_left = ctx->apply_right;
112a3df083aSStefano Zampini   } else {
113a3df083aSStefano Zampini     apply_right = ctx->apply_right;
114a3df083aSStefano Zampini     apply_left = ctx->apply_left;
115a3df083aSStefano Zampini   }
116a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
117a3df083aSStefano Zampini   if (apply_right) {
118a3df083aSStefano Zampini     const PetscScalar *ax;
119a3df083aSStefano Zampini     PetscInt          nl,i;
120a3df083aSStefano Zampini 
121a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
122a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
123a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
124a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
125a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
126a3df083aSStefano Zampini       PetscScalar    sum,val;
127a3df083aSStefano Zampini       const PetscInt *idxs;
128a3df083aSStefano Zampini       PetscInt       nz,j;
129a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
130a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
131a3df083aSStefano Zampini       sum = 0.;
132a3df083aSStefano Zampini       if (ctx->apply_p0) {
133a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
134a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
135a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
136a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
137a3df083aSStefano Zampini         }
138a3df083aSStefano Zampini       } else {
139a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
140a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
141a3df083aSStefano Zampini         }
142a3df083aSStefano Zampini       }
143a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
144a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
145a3df083aSStefano Zampini     }
146a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
147a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
148a3df083aSStefano Zampini   }
149a3df083aSStefano Zampini   if (transpose) {
150a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
151a3df083aSStefano Zampini   } else {
152a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
153a3df083aSStefano Zampini   }
154a3df083aSStefano Zampini   if (reset_x) {
155a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
156a3df083aSStefano Zampini   }
157a3df083aSStefano Zampini   if (apply_left) {
158a3df083aSStefano Zampini     PetscScalar *ay;
159a3df083aSStefano Zampini     PetscInt    i;
160a3df083aSStefano Zampini 
161a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
162a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
163a3df083aSStefano Zampini       PetscScalar    sum,val;
164a3df083aSStefano Zampini       const PetscInt *idxs;
165a3df083aSStefano Zampini       PetscInt       nz,j;
166a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
167a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
168a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
169a3df083aSStefano Zampini       if (ctx->apply_p0) {
170a3df083aSStefano Zampini         sum = 0.;
171a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
172a3df083aSStefano Zampini           sum += ay[idxs[j]];
173a3df083aSStefano Zampini           ay[idxs[j]] += val;
174a3df083aSStefano Zampini         }
175a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
176a3df083aSStefano Zampini       } else {
177a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
178a3df083aSStefano Zampini           ay[idxs[j]] += val;
179a3df083aSStefano Zampini         }
180a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
181a3df083aSStefano Zampini       }
182a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
183a3df083aSStefano Zampini     }
184a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
185a3df083aSStefano Zampini   }
186a3df083aSStefano Zampini   PetscFunctionReturn(0);
187a3df083aSStefano Zampini }
188a3df083aSStefano Zampini 
189a3df083aSStefano Zampini #undef __FUNCT__
190a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
191a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
192a3df083aSStefano Zampini {
193a3df083aSStefano Zampini   PetscErrorCode ierr;
194a3df083aSStefano Zampini 
195a3df083aSStefano Zampini   PetscFunctionBegin;
196a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
197a3df083aSStefano Zampini   PetscFunctionReturn(0);
198a3df083aSStefano Zampini }
199a3df083aSStefano Zampini 
200a3df083aSStefano Zampini #undef __FUNCT__
201a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
202a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
203a3df083aSStefano Zampini {
204a3df083aSStefano Zampini   PetscErrorCode ierr;
205a3df083aSStefano Zampini 
206a3df083aSStefano Zampini   PetscFunctionBegin;
207a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
208a3df083aSStefano Zampini   PetscFunctionReturn(0);
209a3df083aSStefano Zampini }
210a3df083aSStefano Zampini 
211a3df083aSStefano Zampini #undef __FUNCT__
212a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
213a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
214a3df083aSStefano Zampini {
215a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
216a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
217a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
218a3df083aSStefano Zampini   PetscErrorCode          ierr;
219a3df083aSStefano Zampini 
220a3df083aSStefano Zampini   PetscFunctionBegin;
221a3df083aSStefano Zampini   if (!restore) {
2221dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
223a3df083aSStefano Zampini     PetscScalar        *work;
224*b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
225a3df083aSStefano Zampini 
2261dd7afcfSStefano Zampini     if (pcbddc->benign_original_mat) {
2271dd7afcfSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
2281dd7afcfSStefano Zampini     }
2291dd7afcfSStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) {
2301dd7afcfSStefano Zampini       PetscFunctionReturn(0);
2311dd7afcfSStefano Zampini     }
232a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
233a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
234a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
235a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
236a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
237a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
238a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
239a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
240a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
241a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
242a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
243a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
244059032f7SStefano Zampini     if (reuse) {
245a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
2461dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
247059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
248059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
249059032f7SStefano Zampini       PetscInt               i;
250059032f7SStefano Zampini 
251059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
252059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
253059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
254059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
255059032f7SStefano Zampini       }
256059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
2571dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
258059032f7SStefano Zampini     }
259a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
260a3df083aSStefano Zampini     ctx->work = work;
261a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
262a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
263a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
264a3df083aSStefano Zampini     pcis->A_IB = A_IB;
265a3df083aSStefano Zampini 
266a3df083aSStefano Zampini     /* A_BI as A_IB^T */
267a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
268a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
269a3df083aSStefano Zampini     pcis->A_BI = A_BI;
270a3df083aSStefano Zampini   } else {
2711dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
2721dd7afcfSStefano Zampini       PetscFunctionReturn(0);
2731dd7afcfSStefano Zampini     }
274a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
275a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
276a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
2771dd7afcfSStefano Zampini     ctx->A = NULL;
2781dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
2791dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
2801dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
2811dd7afcfSStefano Zampini     if (ctx->free) {
282059032f7SStefano Zampini       PetscInt i;
2831dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
284059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
285059032f7SStefano Zampini       }
286059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
287059032f7SStefano Zampini     }
288a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
289a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
290a3df083aSStefano Zampini   }
291a3df083aSStefano Zampini   PetscFunctionReturn(0);
292a3df083aSStefano Zampini }
293a3df083aSStefano Zampini 
294a3df083aSStefano Zampini /* used just in bddc debug mode */
295a3df083aSStefano Zampini #undef __FUNCT__
296a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
297a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
298a3df083aSStefano Zampini {
299a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
300a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
301a3df083aSStefano Zampini   Mat            An;
302a3df083aSStefano Zampini   PetscErrorCode ierr;
303a3df083aSStefano Zampini 
304a3df083aSStefano Zampini   PetscFunctionBegin;
305a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
306a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
307a3df083aSStefano Zampini   if (is1) {
308a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
309a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
310a3df083aSStefano Zampini   } else {
311a3df083aSStefano Zampini     *B = An;
312a3df083aSStefano Zampini   }
313a3df083aSStefano Zampini   PetscFunctionReturn(0);
314a3df083aSStefano Zampini }
315a3df083aSStefano Zampini 
3161cf9b237SStefano Zampini /* TODO: add reuse flag */
3171cf9b237SStefano Zampini #undef __FUNCT__
3181cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
3191cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
3201cf9b237SStefano Zampini {
3211cf9b237SStefano Zampini   Mat            Bt;
3221cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
3231cf9b237SStefano Zampini   const PetscInt *ii,*ij;
3241cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
3251cf9b237SStefano Zampini   PetscBool      flg_row;
3261cf9b237SStefano Zampini   PetscErrorCode ierr;
3271cf9b237SStefano Zampini 
3281cf9b237SStefano Zampini   PetscFunctionBegin;
3291cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
3301cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
3311cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
3321cf9b237SStefano Zampini   nnz = n;
3331cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
3341cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
3351cf9b237SStefano Zampini   }
3361cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
3371cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
3381cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
3391cf9b237SStefano Zampini   nnz = 0;
3401cf9b237SStefano Zampini   bii[0] = 0;
3411cf9b237SStefano Zampini   for (i=0;i<n;i++) {
3421cf9b237SStefano Zampini     PetscInt j;
3431cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
3441cf9b237SStefano Zampini       PetscScalar entry = a[j];
3451cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
3461cf9b237SStefano Zampini         bij[nnz] = ij[j];
3471cf9b237SStefano Zampini         bdata[nnz] = entry;
3481cf9b237SStefano Zampini         nnz++;
3491cf9b237SStefano Zampini       }
3501cf9b237SStefano Zampini     }
3511cf9b237SStefano Zampini     bii[i+1] = nnz;
3521cf9b237SStefano Zampini   }
3531cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
3541cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
3551cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
3561cf9b237SStefano Zampini   {
3571cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
3581cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
3591cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
3601cf9b237SStefano Zampini   }
3611cf9b237SStefano Zampini   *B = Bt;
3621cf9b237SStefano Zampini   PetscFunctionReturn(0);
3631cf9b237SStefano Zampini }
3641cf9b237SStefano Zampini 
365674ae819SStefano Zampini #undef __FUNCT__
3664f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
3674f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
3684f1b2e48SStefano Zampini {
3694f1b2e48SStefano Zampini   Mat                    B;
3704f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
3714f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
3724f1b2e48SStefano Zampini   PCBDDCGraph            graph;
3734f1b2e48SStefano Zampini   PetscInt               i,n;
3744f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
3754f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
3764f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
3774f1b2e48SStefano Zampini   PetscErrorCode         ierr;
3784f1b2e48SStefano Zampini 
3794f1b2e48SStefano Zampini   PetscFunctionBegin;
38063c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
38163c961adSStefano Zampini     *ncc = 0;
38263c961adSStefano Zampini     *cc = NULL;
38363c961adSStefano Zampini     PetscFunctionReturn(0);
38463c961adSStefano Zampini   }
3854f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
3864f1b2e48SStefano Zampini   if (!isseqaij && filter) {
3871cf9b237SStefano Zampini     PetscBool isseqdense;
3881cf9b237SStefano Zampini 
3891cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
3901cf9b237SStefano Zampini     if (!isseqdense) {
3914f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
3921cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
3931cf9b237SStefano Zampini       PetscScalar *array;
3941cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
3951cf9b237SStefano Zampini 
3961cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
3971cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
3981cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
3991cf9b237SStefano Zampini       for (i=0;i<n;i++) {
4001cf9b237SStefano Zampini         PetscInt j;
4011cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
4021cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
4031cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
4041cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
4051cf9b237SStefano Zampini         }
4061cf9b237SStefano Zampini       }
4071cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
4089d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
4091cf9b237SStefano Zampini     }
4104f1b2e48SStefano Zampini   } else {
4114f1b2e48SStefano Zampini     B = A;
4124f1b2e48SStefano Zampini   }
4134f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4144f1b2e48SStefano Zampini 
4154f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
4164f1b2e48SStefano Zampini   if (filter) {
4174f1b2e48SStefano Zampini     PetscScalar *data;
4184f1b2e48SStefano Zampini     PetscInt    j,cum;
4194f1b2e48SStefano Zampini 
4204f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
4214f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
4224f1b2e48SStefano Zampini     cum = 0;
4234f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
4244f1b2e48SStefano Zampini       PetscInt t;
4254f1b2e48SStefano Zampini 
4264f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
4274f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
4284f1b2e48SStefano Zampini           continue;
4294f1b2e48SStefano Zampini         }
4304f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
4314f1b2e48SStefano Zampini       }
4324f1b2e48SStefano Zampini       t = xadj_filtered[i];
4334f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
4344f1b2e48SStefano Zampini       cum += t;
4354f1b2e48SStefano Zampini     }
4364f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
4374f1b2e48SStefano Zampini   } else {
4384f1b2e48SStefano Zampini     xadj_filtered = NULL;
4394f1b2e48SStefano Zampini     adjncy_filtered = NULL;
4404f1b2e48SStefano Zampini   }
4414f1b2e48SStefano Zampini 
4424f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
4434f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
4444f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
4454f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4464f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
4474f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
4484f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
4494f1b2e48SStefano Zampini   if (xadj_filtered) {
4504f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
4514f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
4524f1b2e48SStefano Zampini   } else {
4534f1b2e48SStefano Zampini     graph->xadj = xadj;
4544f1b2e48SStefano Zampini     graph->adjncy = adjncy;
4554f1b2e48SStefano Zampini   }
4564f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
4574f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4584f1b2e48SStefano Zampini   /* partial clean up */
4594f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
4604f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4611cf9b237SStefano Zampini   if (A != B) {
4624f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
4634f1b2e48SStefano Zampini   }
4644f1b2e48SStefano Zampini 
4654f1b2e48SStefano Zampini   /* get back data */
4661cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
4671cf9b237SStefano Zampini   if (cc) {
4684f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
4694f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
4704f1b2e48SStefano 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);
4714f1b2e48SStefano Zampini     }
4724f1b2e48SStefano Zampini     *cc = cc_n;
4731cf9b237SStefano Zampini   }
4744f1b2e48SStefano Zampini   /* clean up graph */
4754f1b2e48SStefano Zampini   graph->xadj = 0;
4764f1b2e48SStefano Zampini   graph->adjncy = 0;
4774f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
4784f1b2e48SStefano Zampini   PetscFunctionReturn(0);
4794f1b2e48SStefano Zampini }
4804f1b2e48SStefano Zampini 
4814f1b2e48SStefano Zampini #undef __FUNCT__
4825408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
4835408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
4845408967cSStefano Zampini {
4855408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4865408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
487dee84bffSStefano Zampini   IS             dirIS = NULL;
4884f1b2e48SStefano Zampini   PetscInt       i;
4895408967cSStefano Zampini   PetscErrorCode ierr;
4905408967cSStefano Zampini 
4915408967cSStefano Zampini   PetscFunctionBegin;
492dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
4935408967cSStefano Zampini   if (zerodiag) {
4945408967cSStefano Zampini     Mat            A;
4955408967cSStefano Zampini     Vec            vec3_N;
4965408967cSStefano Zampini     PetscScalar    *vals;
4975408967cSStefano Zampini     const PetscInt *idxs;
498d12d3064SStefano Zampini     PetscInt       nz,*count;
4995408967cSStefano Zampini 
5005408967cSStefano Zampini     /* p0 */
5015408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
5025408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
5035408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
5045408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
5054f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
5065408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5075408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5085408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5095408967cSStefano Zampini     /* v_I */
5105408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
5115408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
5125408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5135408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
5145408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
5155408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
5165408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5175408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
5185408967cSStefano Zampini     if (dirIS) {
5195408967cSStefano Zampini       PetscInt n;
5205408967cSStefano Zampini 
5215408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
5225408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
5235408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
5245408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5255408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
5265408967cSStefano Zampini     }
5275408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
5285408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
5295408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
5305408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
5315408967cSStefano Zampini     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
5325408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
5335408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
534fbfcb133SStefano Zampini     if (PetscAbsScalar(vals[0]) > 1.e-1) {
535b9b0e38cSStefano 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]));
5365408967cSStefano Zampini     }
5375408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
5385408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
539d12d3064SStefano Zampini 
540d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
541d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
542d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
543d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
544d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
545d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
546d4d8cf7bSStefano Zampini     for (i=0;i<nz;i++) {
547d12d3064SStefano Zampini       if (count[idxs[i]]) {
548d12d3064SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
549d12d3064SStefano Zampini       }
550d4d8cf7bSStefano Zampini     }
551d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
552d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
5535408967cSStefano Zampini   }
554dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
5555408967cSStefano Zampini 
5565408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
5575408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
5584f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
5595408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
5604f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
5615408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
5624f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
5634f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
5644f1b2e48SStefano 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);
5654f1b2e48SStefano Zampini     }
5665408967cSStefano Zampini   }
5675408967cSStefano Zampini   PetscFunctionReturn(0);
5685408967cSStefano Zampini }
5695408967cSStefano Zampini 
5705408967cSStefano Zampini #undef __FUNCT__
571339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
572339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
573339f8db1SStefano Zampini {
574339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5754f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
576b0f5fe93SStefano Zampini   PetscInt       nz,n;
5771f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
5784f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
579339f8db1SStefano Zampini   PetscErrorCode ierr;
580339f8db1SStefano Zampini 
581339f8db1SStefano Zampini   PetscFunctionBegin;
5829f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
5839f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
584a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
585a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
586a3df083aSStefano Zampini   }
587a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
588a3df083aSStefano Zampini   pcbddc->benign_n = 0;
5894f1b2e48SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
5904f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
5914f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
5924f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
5934f1b2e48SStefano Zampini      since the local Schur complements are SPD
5944f1b2e48SStefano Zampini   */
5954f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
5964f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
59740fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
5984f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
5994f1b2e48SStefano Zampini 
6004f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
6014f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
6024f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
6034f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
604ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
60540fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
60640fa8d13SStefano Zampini     if (!sorted) {
60740fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
60840fa8d13SStefano Zampini     }
60940fa8d13SStefano Zampini   } else {
61040fa8d13SStefano Zampini     pressures = NULL;
61140fa8d13SStefano Zampini   }
61297d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
61397d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
61427b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
61597d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
616339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
617339f8db1SStefano Zampini   if (!sorted) {
618339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
619339f8db1SStefano Zampini   }
620339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
6214f1b2e48SStefano Zampini   if (!nz) {
6224f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
6234f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
62440fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
62540fa8d13SStefano Zampini   }
6264f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
6274f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
6284f1b2e48SStefano Zampini   zerodiag_subs = NULL;
6294f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
6301f4df5f7SStefano Zampini   n_interior_dofs = 0;
6311f4df5f7SStefano Zampini   interior_dofs = NULL;
6321f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
6331f4df5f7SStefano Zampini     PetscInt n,i,j;
6341f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
6351f4df5f7SStefano Zampini     PetscInt *iwork;
6361f4df5f7SStefano Zampini 
6371f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
6381f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6391f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
6401f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
6411f4df5f7SStefano Zampini     for (i=0;i<n_neigh;i++)
6421f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
6431f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
6441f4df5f7SStefano Zampini     for (i=0;i<n;i++)
6451f4df5f7SStefano Zampini       if (!iwork[i])
6461f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
6471f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
6481f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6491f4df5f7SStefano Zampini   }
6504f1b2e48SStefano Zampini   if (has_null_pressures) {
6514f1b2e48SStefano Zampini     IS             *subs;
6521f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
6531f4df5f7SStefano Zampini     const PetscInt *idxs;
6541f4df5f7SStefano Zampini     PetscScalar    *array;
6551f4df5f7SStefano Zampini     Vec            *work;
6561f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
6574f1b2e48SStefano Zampini 
6584f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
6594f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
6601f4df5f7SStefano 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) */
6611f4df5f7SStefano Zampini     if (pcbddc->current_level) {
6621f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
6631f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
6641f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
6651f4df5f7SStefano Zampini       /* work[0] = 1_p */
6661f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
6671f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
6681f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
6691f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
6701f4df5f7SStefano Zampini       /* work[0] = 1_v */
6711f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
6721f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
6731f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
6741f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
6751f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
6761f4df5f7SStefano Zampini     }
6774f1b2e48SStefano Zampini     if (nsubs > 1) {
6784f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
6794f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
6804f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
6814f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
6824f1b2e48SStefano Zampini         PetscInt               nl;
6834f1b2e48SStefano Zampini 
6844f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
6854f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
6864f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
6874f1b2e48SStefano Zampini         if (nl) {
6884f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
6894f1b2e48SStefano Zampini 
6901f4df5f7SStefano Zampini           if (pcbddc->current_level) {
6911f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
6921f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
6931f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
6941f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
6951f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
6961f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
6971f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
6981f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
6991f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
7001f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
7011f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
7021f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
7031f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
7041f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
7051f4df5f7SStefano Zampini                 break;
7061f4df5f7SStefano Zampini               }
7071f4df5f7SStefano Zampini             }
7081f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
7091f4df5f7SStefano Zampini           }
7101f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
7111f4df5f7SStefano Zampini             IS       t_bc;
7121f4df5f7SStefano Zampini             PetscInt nzb;
7131f4df5f7SStefano Zampini 
7141f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
7151f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
7161f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
7171f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
7181f4df5f7SStefano Zampini           }
7191f4df5f7SStefano Zampini           if (valid && pressures) {
7204f1b2e48SStefano Zampini             IS t_pressure_subs;
7214f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
7224f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
7234f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
7244f1b2e48SStefano Zampini           }
7254f1b2e48SStefano Zampini           if (valid) {
7264f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
7274f1b2e48SStefano Zampini             pcbddc->benign_n++;
7284f1b2e48SStefano Zampini           } else {
7294f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
7304f1b2e48SStefano Zampini           }
7314f1b2e48SStefano Zampini         }
7324f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
7334f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
7344f1b2e48SStefano Zampini       }
7354f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
7364f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
7371f4df5f7SStefano Zampini 
7381f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
7391f4df5f7SStefano Zampini         PetscInt nzb;
7401f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
7411f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
7421f4df5f7SStefano Zampini       }
7431f4df5f7SStefano Zampini       if (valid && pressures) {
7444f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
7454f1b2e48SStefano Zampini       }
7461f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
7471f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
7481f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
7491f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
7501f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
7511f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
7521f4df5f7SStefano Zampini               valid = PETSC_FALSE;
7531f4df5f7SStefano Zampini               break;
7541f4df5f7SStefano Zampini           }
7551f4df5f7SStefano Zampini         }
7561f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
7571f4df5f7SStefano Zampini       }
7584f1b2e48SStefano Zampini       if (valid) {
7594f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
760ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
7614f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
7624f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
7634f1b2e48SStefano Zampini       }
7644f1b2e48SStefano Zampini     }
7651f4df5f7SStefano Zampini     if (pcbddc->current_level) {
7661f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
7674f1b2e48SStefano Zampini     }
7681f4df5f7SStefano Zampini   }
7691f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
7704f1b2e48SStefano Zampini 
7714f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
772b9b0e38cSStefano Zampini     PetscInt n;
773b9b0e38cSStefano Zampini 
7744f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
7754f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
776b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
777b9b0e38cSStefano Zampini     if (n) {
7784f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
7794f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
7804f1b2e48SStefano Zampini     }
781b9b0e38cSStefano Zampini   }
7824f1b2e48SStefano Zampini 
7834f1b2e48SStefano Zampini   /* final check for null pressures */
7844f1b2e48SStefano Zampini   if (zerodiag && pressures) {
7854f1b2e48SStefano Zampini     PetscInt nz,np;
7864f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
7874f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
7884f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
7894f1b2e48SStefano Zampini   }
7904f1b2e48SStefano Zampini 
7914f1b2e48SStefano Zampini   if (recompute_zerodiag) {
7924f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
7934f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
7944f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
7954f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
7964f1b2e48SStefano Zampini     } else {
7974f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
7984f1b2e48SStefano Zampini 
7994f1b2e48SStefano Zampini       nzn = 0;
8004f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
8014f1b2e48SStefano Zampini         PetscInt ns;
8024f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
8034f1b2e48SStefano Zampini         nzn += ns;
8044f1b2e48SStefano Zampini       }
8054f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
8064f1b2e48SStefano Zampini       nzn = 0;
8074f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
8084f1b2e48SStefano Zampini         PetscInt ns,*idxs;
8094f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
8104f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
8114f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
8124f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
8134f1b2e48SStefano Zampini         nzn += ns;
8144f1b2e48SStefano Zampini       }
8154f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
8164f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
8174f1b2e48SStefano Zampini     }
8184f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
8194f1b2e48SStefano Zampini   }
8204f1b2e48SStefano Zampini 
821b3afcdbeSStefano Zampini   /* no-net-flux */
822b3afcdbeSStefano Zampini   if (pcbddc->benign_compute_nonetflux) {
823b3afcdbeSStefano Zampini     Mat_IS*                matis = (Mat_IS*)(pc->pmat->data);
824b3afcdbeSStefano Zampini     MatNullSpace           near_null_space;
825b3afcdbeSStefano Zampini     ISLocalToGlobalMapping rmap;
826b3afcdbeSStefano Zampini     Vec                    quad_vec;
827b3afcdbeSStefano Zampini     PetscScalar            *pvals;
828b3afcdbeSStefano Zampini     PetscInt               i,np,*dummyins;
8291f4df5f7SStefano Zampini     IS                     isused = NULL;
8301f4df5f7SStefano Zampini     PetscBool              participate = PETSC_TRUE;
831b3afcdbeSStefano Zampini 
832b3afcdbeSStefano Zampini     /* create vector to hold quadrature weights */
833b3afcdbeSStefano Zampini     ierr = MatCreateVecs(pc->pmat,&quad_vec,NULL);CHKERRQ(ierr);
834b3afcdbeSStefano Zampini     ierr = VecSet(quad_vec,0.0);CHKERRQ(ierr);
835b3afcdbeSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&rmap,NULL);CHKERRQ(ierr);
836b3afcdbeSStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vec,rmap);CHKERRQ(ierr);
837b3afcdbeSStefano Zampini 
838b3afcdbeSStefano Zampini     /* compute B^{(i)T} * 1_p */
839b3afcdbeSStefano Zampini     np = 0;
8401f4df5f7SStefano Zampini     if (pressures) {
8411f4df5f7SStefano Zampini       isused = pressures;
8421f4df5f7SStefano Zampini     } else {
8431f4df5f7SStefano Zampini       isused = zerodiag;
8441f4df5f7SStefano Zampini     }
8451f4df5f7SStefano Zampini     if (isused) {
8461f4df5f7SStefano Zampini       ierr = ISGetLocalSize(isused,&np);CHKERRQ(ierr);
847b3afcdbeSStefano Zampini     }
848b3afcdbeSStefano Zampini     ierr = PetscMalloc1(np,&pvals);CHKERRQ(ierr);
849b3afcdbeSStefano Zampini     for (i=0;i<np;i++) pvals[i] = 1.;
850b3afcdbeSStefano Zampini     ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
851b3afcdbeSStefano Zampini     if (np) {
852b3afcdbeSStefano Zampini       const PetscInt *pidxs;
853b3afcdbeSStefano Zampini 
8541f4df5f7SStefano Zampini       if (isused) {
8551f4df5f7SStefano Zampini         ierr = ISGetIndices(isused,&pidxs);CHKERRQ(ierr);
856b3afcdbeSStefano Zampini       }
857b3afcdbeSStefano Zampini       ierr = VecSetValues(matis->x,np,pidxs,pvals,INSERT_VALUES);CHKERRQ(ierr);
8581f4df5f7SStefano Zampini       if (isused) {
8591f4df5f7SStefano Zampini         ierr = ISRestoreIndices(isused,&pidxs);CHKERRQ(ierr);
860b3afcdbeSStefano Zampini       }
861b3afcdbeSStefano Zampini     }
862b3afcdbeSStefano Zampini     ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
863b3afcdbeSStefano Zampini     ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
864b3afcdbeSStefano Zampini     ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
865b3afcdbeSStefano Zampini     ierr = PetscFree(pvals);CHKERRQ(ierr);
8661f4df5f7SStefano Zampini     if (!isused) participate = PETSC_FALSE;
867b3afcdbeSStefano Zampini     /* decide which of the sharing ranks (per dof) has to insert the values (should just be a matter of having a different orientation) */
868b3afcdbeSStefano Zampini     ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
869daf8a457SStefano Zampini     for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = -1;
8701f4df5f7SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++)
8711f4df5f7SStefano Zampini       if (participate) matis->sf_leafdata[i] = PetscGlobalRank;
8721f4df5f7SStefano Zampini       else  matis->sf_leafdata[i] = -1;
8731f4df5f7SStefano Zampini 
874b3afcdbeSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_MAX);CHKERRQ(ierr);
875b3afcdbeSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_MAX);CHKERRQ(ierr);
876b3afcdbeSStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
877b3afcdbeSStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
878b3afcdbeSStefano Zampini     ierr = VecGetArray(matis->y,&pvals);CHKERRQ(ierr);
879daf8a457SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++) {
880b3afcdbeSStefano Zampini       if (PetscGlobalRank != matis->sf_leafdata[i]) {
881b3afcdbeSStefano Zampini         pvals[i] = 0.;
882b3afcdbeSStefano Zampini       }
883b3afcdbeSStefano Zampini     }
884daf8a457SStefano Zampini     ierr = PetscMalloc1(matis->sf->nleaves,&dummyins);CHKERRQ(ierr);
885daf8a457SStefano Zampini     for (i=0;i<matis->sf->nleaves;i++) dummyins[i] = i;
886daf8a457SStefano Zampini     ierr = VecSetValuesLocal(quad_vec,matis->sf->nleaves,dummyins,pvals,ADD_VALUES);CHKERRQ(ierr);
887b3afcdbeSStefano Zampini     ierr = VecRestoreArray(matis->y,&pvals);CHKERRQ(ierr);
888b3afcdbeSStefano Zampini     ierr = PetscFree(dummyins);CHKERRQ(ierr);
889b3afcdbeSStefano Zampini 
890b3afcdbeSStefano Zampini     /* assembly quadrature vec and attach near null space to pmat */
891b3afcdbeSStefano Zampini     ierr = VecAssemblyBegin(quad_vec);CHKERRQ(ierr);
892b3afcdbeSStefano Zampini     ierr = VecAssemblyEnd(quad_vec);CHKERRQ(ierr);
893b3afcdbeSStefano Zampini     ierr = VecNormalize(quad_vec,NULL);CHKERRQ(ierr);
894b3afcdbeSStefano Zampini     ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,1,&quad_vec,&near_null_space);CHKERRQ(ierr);
895b3afcdbeSStefano Zampini     ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
896b3afcdbeSStefano Zampini     ierr = MatSetNearNullSpace(pc->pmat,near_null_space);CHKERRQ(ierr);
897b3afcdbeSStefano Zampini     ierr = MatNullSpaceDestroy(&near_null_space);CHKERRQ(ierr);
898b3afcdbeSStefano Zampini   }
899b3afcdbeSStefano Zampini 
900b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
9014f1b2e48SStefano Zampini   if (has_null_pressures) {
9024f1b2e48SStefano Zampini     IS             zerodiagc;
9034f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
9044f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
9054f1b2e48SStefano Zampini 
9064f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
907339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
908339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
909339f8db1SStefano Zampini     /* local change of basis for pressures */
910339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
91197d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
912339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
913339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
914339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
9154f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
9164f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
9174f1b2e48SStefano Zampini       PetscInt nzs,j;
9184f1b2e48SStefano Zampini 
9194f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
9204f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
9214f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
9224f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
9234f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
9244f1b2e48SStefano Zampini     }
925339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
926339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
927339f8db1SStefano Zampini     /* set identity on velocities */
928339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
929339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
930339f8db1SStefano Zampini     }
9314f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
9324f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
9339f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
9344f1b2e48SStefano 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);
935339f8db1SStefano Zampini     /* set change on pressures */
9364f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
9374f1b2e48SStefano Zampini       PetscScalar *array;
9384f1b2e48SStefano Zampini       PetscInt    nzs;
9394f1b2e48SStefano Zampini 
9404f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
9414f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
9424f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
943339f8db1SStefano Zampini         PetscScalar vals[2];
944339f8db1SStefano Zampini         PetscInt    cols[2];
945339f8db1SStefano Zampini 
946339f8db1SStefano Zampini         cols[0] = idxs[i];
9474f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
948339f8db1SStefano Zampini         vals[0] = 1.;
949b0f5fe93SStefano Zampini         vals[1] = 1.;
9504f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
951339f8db1SStefano Zampini       }
9524f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
9534f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
9544f1b2e48SStefano Zampini       array[nzs-1] = 1.;
9554f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
9564f1b2e48SStefano Zampini       /* store local idxs for p0 */
9574f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
9584f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
959339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
9604f1b2e48SStefano Zampini     }
961339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
962339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
963a3df083aSStefano Zampini     /* project if needed */
964a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
9651dd7afcfSStefano Zampini       Mat M;
9661dd7afcfSStefano Zampini 
9671dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
968339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
9691dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
9701dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
971a3df083aSStefano Zampini     }
9724f1b2e48SStefano Zampini     /* store global idxs for p0 */
9734f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
974339f8db1SStefano Zampini   }
975ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
9764f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
977b0f5fe93SStefano Zampini 
978b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
979b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
98027b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
98127b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
982339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
983339f8db1SStefano Zampini   PetscFunctionReturn(0);
984339f8db1SStefano Zampini }
985339f8db1SStefano Zampini 
986339f8db1SStefano Zampini #undef __FUNCT__
987015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
988015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
989efc2fbd9SStefano Zampini {
990efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
991de9d7bd0SStefano Zampini   PetscScalar    *array;
992efc2fbd9SStefano Zampini   PetscErrorCode ierr;
993efc2fbd9SStefano Zampini 
994efc2fbd9SStefano Zampini   PetscFunctionBegin;
995efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
996efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
9974f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
998efc2fbd9SStefano Zampini   }
999de9d7bd0SStefano Zampini   if (get) {
1000efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
10014f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
10024f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
1003efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
1004de9d7bd0SStefano Zampini   } else {
1005de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
1006de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1007de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1008de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
1009efc2fbd9SStefano Zampini   }
1010efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
1011efc2fbd9SStefano Zampini }
1012efc2fbd9SStefano Zampini 
1013efc2fbd9SStefano Zampini #undef __FUNCT__
1014c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
1015c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
1016c263805aSStefano Zampini {
1017c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1018c263805aSStefano Zampini   PetscErrorCode ierr;
1019c263805aSStefano Zampini 
1020c263805aSStefano Zampini   PetscFunctionBegin;
1021c263805aSStefano Zampini   /* TODO: add error checking
1022c263805aSStefano Zampini     - avoid nested pop (or push) calls.
1023c263805aSStefano Zampini     - cannot push before pop.
10241c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
1025c263805aSStefano Zampini   */
10264f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1027efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
1028efc2fbd9SStefano Zampini   }
1029c263805aSStefano Zampini   if (pop) {
1030a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
10314f1b2e48SStefano Zampini       IS       is_p0;
10324f1b2e48SStefano Zampini       MatReuse reuse;
1033c263805aSStefano Zampini 
1034c263805aSStefano Zampini       /* extract B_0 */
10354f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
10364f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
10374f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
10384f1b2e48SStefano Zampini       }
10394f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
10404f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
1041c263805aSStefano Zampini       /* remove rows and cols from local problem */
1042c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
104397d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
10444f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
10454f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
1046a3df083aSStefano Zampini     } else {
1047a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
1048a3df083aSStefano Zampini       PetscScalar *vals;
1049a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
1050a3df083aSStefano Zampini 
1051a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
1052a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
1053a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
10540b5adadeSStefano Zampini         PetscInt *nnz;
1055a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
1056a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
1057a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1058331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
1059331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
1060331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
1061331e053bSStefano Zampini           nnz[i] = n - nnz[i];
1062331e053bSStefano Zampini         }
1063331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
1064331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
1065331e053bSStefano Zampini       }
1066a3df083aSStefano Zampini 
1067a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1068a3df083aSStefano Zampini         PetscScalar *array;
1069a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
1070a3df083aSStefano Zampini 
1071a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
1072a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1073a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1074a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
1075a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1076a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
1077a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
1078a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
1079a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
1080a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
1081a3df083aSStefano Zampini         cum = 0;
1082a3df083aSStefano Zampini         for (j=0;j<n;j++) {
108322db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
1084a3df083aSStefano Zampini             vals[cum] = array[j];
1085a3df083aSStefano Zampini             idxs_ins[cum] = j;
1086a3df083aSStefano Zampini             cum++;
1087a3df083aSStefano Zampini           }
1088a3df083aSStefano Zampini         }
1089a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
1090a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
1091a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1092a3df083aSStefano Zampini       }
1093a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1094a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1095a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
1096a3df083aSStefano Zampini     }
1097c263805aSStefano Zampini   } else { /* push */
1098a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
10994f1b2e48SStefano Zampini       PetscInt i;
11004f1b2e48SStefano Zampini 
11014f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
11024f1b2e48SStefano Zampini         PetscScalar *B0_vals;
11034f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
11044f1b2e48SStefano Zampini 
11054f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
11064f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
11077b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
11084f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
11094f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
11104f1b2e48SStefano Zampini       }
1111c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1112c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1113a3df083aSStefano Zampini     } else {
1114a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
1115a3df083aSStefano Zampini     }
1116c263805aSStefano Zampini   }
1117c263805aSStefano Zampini   PetscFunctionReturn(0);
1118c263805aSStefano Zampini }
1119c263805aSStefano Zampini 
1120c263805aSStefano Zampini #undef __FUNCT__
1121b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
112208122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
1123b1b3d7a2SStefano Zampini {
1124b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
112508122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
112608122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
112708122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
112808122e43SStefano Zampini   PetscScalar     *work,lwork;
112908122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
113008122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
113108122e43SStefano Zampini   PetscReal       *eigs,thresh;
11321b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
1133f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
113408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
113508122e43SStefano Zampini   PetscReal       *rwork;
113608122e43SStefano Zampini #endif
1137b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
1138b1b3d7a2SStefano Zampini 
1139b1b3d7a2SStefano Zampini   PetscFunctionBegin;
1140*b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
1141af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
1142af25d912SStefano 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);
114306a4e24aSStefano Zampini 
1144fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1145fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1146fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1147fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
11481575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1149fd14bc51SStefano Zampini   }
1150fd14bc51SStefano Zampini 
1151e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
1152e496cd5dSStefano 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);
1153e496cd5dSStefano Zampini   }
1154e496cd5dSStefano Zampini 
115508122e43SStefano Zampini   /* max size of subsets */
115608122e43SStefano Zampini   mss = 0;
115708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
115808122e43SStefano Zampini     PetscInt subset_size;
1159862806e4SStefano Zampini 
116008122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
116108122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
116208122e43SStefano Zampini   }
116308122e43SStefano Zampini 
116408122e43SStefano Zampini   /* min/max and threshold */
116508122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
1166f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
116708122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
1168f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
1169f6f667cfSStefano Zampini   if (nmin) {
1170f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
1171f6f667cfSStefano Zampini   }
117208122e43SStefano Zampini 
117308122e43SStefano Zampini   /* allocate lapack workspace */
117408122e43SStefano Zampini   cum = cum2 = 0;
117508122e43SStefano Zampini   maxneigs = 0;
117608122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
117708122e43SStefano Zampini     PetscInt n,subset_size;
1178f6f667cfSStefano Zampini 
117908122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
118008122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
11819162d606SStefano Zampini     cum += subset_size;
11829162d606SStefano Zampini     cum2 += subset_size*n;
118308122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
118408122e43SStefano Zampini   }
118508122e43SStefano Zampini   if (mss) {
11869ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
118708122e43SStefano Zampini       PetscBLASInt B_itype = 1;
118808122e43SStefano Zampini       PetscBLASInt B_N = mss;
11894c6709b3SStefano Zampini       PetscReal    zero = 0.0;
11904c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
119108122e43SStefano Zampini 
119208122e43SStefano Zampini       B_lwork = -1;
119308122e43SStefano Zampini       S = NULL;
119408122e43SStefano Zampini       St = NULL;
1195a58a30b4SStefano Zampini       eigs = NULL;
1196a58a30b4SStefano Zampini       eigv = NULL;
1197a58a30b4SStefano Zampini       B_iwork = NULL;
1198a58a30b4SStefano Zampini       B_ifail = NULL;
1199d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1200d1710679SStefano Zampini       rwork = NULL;
1201d1710679SStefano Zampini #endif
12028bec7fa6SStefano Zampini       thresh = 1.0;
120308122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
120408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
120508122e43SStefano 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));
120608122e43SStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
120808122e43SStefano Zampini #endif
120908122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
121008122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
121108122e43SStefano Zampini     } else {
121208122e43SStefano Zampini         /* TODO */
121308122e43SStefano Zampini     }
121408122e43SStefano Zampini   } else {
121508122e43SStefano Zampini     lwork = 0;
121608122e43SStefano Zampini   }
121708122e43SStefano Zampini 
121808122e43SStefano Zampini   nv = 0;
1219d62866d3SStefano 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) */
1220d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
122108122e43SStefano Zampini   }
12224c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
1223f6f667cfSStefano Zampini   if (allocated_S_St) {
1224f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
1225f6f667cfSStefano Zampini   }
1226f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
122708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
122808122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
122908122e43SStefano Zampini #endif
12309162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
12319162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
12329162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
123308122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
12349162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
123508122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
123608122e43SStefano Zampini 
123708122e43SStefano Zampini   maxneigs = 0;
123872b8c272SStefano Zampini   cum = cumarray = 0;
12399162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
12409162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
1241d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
124208122e43SStefano Zampini     const PetscInt *idxs;
124308122e43SStefano Zampini 
1244d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
124508122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
124608122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
124708122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
124808122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
12499162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
12509162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
125108122e43SStefano Zampini     }
1252d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
125308122e43SStefano Zampini   }
125408122e43SStefano Zampini 
125508122e43SStefano Zampini   if (mss) { /* multilevel */
125608122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
125708122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
125808122e43SStefano Zampini   }
125908122e43SStefano Zampini 
1260ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
126108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
126208122e43SStefano Zampini     const PetscInt *idxs;
12639d54b7f4SStefano Zampini     PetscReal      upper,lower;
1264862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
126508122e43SStefano Zampini     PetscBLASInt   B_N;
1266aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
126708122e43SStefano Zampini 
12689d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
12699d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
12709d54b7f4SStefano Zampini       lower = thresh;
12719d54b7f4SStefano Zampini     } else {
12729d54b7f4SStefano Zampini       upper = 1./thresh;
12739d54b7f4SStefano Zampini       lower = 0.;
12749d54b7f4SStefano Zampini     }
1275862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
1276ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
1277f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
1278f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
12799ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
1280aff50787SStefano Zampini         PetscInt j,k;
1281aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
1282aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1283aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
128408122e43SStefano Zampini         }
128508122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1286aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1287aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1288aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1289aff50787SStefano Zampini           }
129008122e43SStefano Zampini         }
129108122e43SStefano Zampini       } else {
129208122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
129308122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
129408122e43SStefano Zampini       }
12958bec7fa6SStefano Zampini     } else {
1296f6f667cfSStefano Zampini       S = Sarray + cumarray;
1297f6f667cfSStefano Zampini       St = Starray + cumarray;
12988bec7fa6SStefano Zampini     }
1299aff50787SStefano Zampini     /* see if we can save some work */
1300b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
1301aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1302aff50787SStefano Zampini     }
1303aff50787SStefano Zampini 
1304b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
1305aff50787SStefano Zampini       B_neigs = 0;
1306aff50787SStefano Zampini     } else {
13079ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
130808122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1309f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
13104c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
13119552c7c7SStefano Zampini         PetscInt     nmin_s;
1312b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
131308122e43SStefano Zampini 
1314fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
13158bec7fa6SStefano 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]]);
1316fd14bc51SStefano Zampini         }
1317d16cbb6bSStefano Zampini 
1318b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
1319b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
1320b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
1321b7ab4a40SStefano Zampini         }
1322b7ab4a40SStefano Zampini 
132308122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1324b7ab4a40SStefano Zampini         if (compute_range) {
1325d16cbb6bSStefano Zampini 
1326d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
132708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
13289d54b7f4SStefano 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));
132908122e43SStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
133108122e43SStefano Zampini #endif
1332b7ab4a40SStefano Zampini         } else if (!same_data) {
1333d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1334d16cbb6bSStefano Zampini           B_IL = 1;
1335d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
13369d54b7f4SStefano 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));
1337d16cbb6bSStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
1339d16cbb6bSStefano Zampini #endif
1340b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
1341b7ab4a40SStefano Zampini           PetscInt k;
1342b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
1343b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
1344b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
1345b7ab4a40SStefano Zampini           nmin = nmax;
1346b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1347b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
1348b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
1349b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
1350b7ab4a40SStefano Zampini           }
1351d16cbb6bSStefano Zampini         }
135208122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
135308122e43SStefano Zampini         if (B_ierr) {
13546c4ed002SBarry 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);
13556c4ed002SBarry 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);
13566c4ed002SBarry 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);
135708122e43SStefano Zampini         }
135808122e43SStefano Zampini 
135908122e43SStefano Zampini         if (B_neigs > nmax) {
1360fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1361fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1362fd14bc51SStefano Zampini           }
13639d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
136408122e43SStefano Zampini           B_neigs = nmax;
136508122e43SStefano Zampini         }
136608122e43SStefano Zampini 
13679552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
13689552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
136908122e43SStefano Zampini           PetscBLASInt B_neigs2;
137008122e43SStefano Zampini 
13719d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
1372f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
13739d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
13749d54b7f4SStefano Zampini           } else {
13759d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
13769d54b7f4SStefano Zampini             B_IU = nmin_s;
13779d54b7f4SStefano Zampini           }
1378fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1379fd14bc51SStefano 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);
1380fd14bc51SStefano Zampini           }
13819ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
138208122e43SStefano Zampini             PetscInt j;
138308122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
138408122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
138508122e43SStefano Zampini             }
138608122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
138708122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
138808122e43SStefano Zampini             }
138908122e43SStefano Zampini           } else {
139008122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139108122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139208122e43SStefano Zampini           }
139308122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
139408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
13959d54b7f4SStefano 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));
139608122e43SStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
139808122e43SStefano Zampini #endif
139908122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
140008122e43SStefano Zampini           B_neigs += B_neigs2;
140108122e43SStefano Zampini         }
140208122e43SStefano Zampini         if (B_ierr) {
14036c4ed002SBarry 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);
14046c4ed002SBarry 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);
14056c4ed002SBarry 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);
140608122e43SStefano Zampini         }
1407fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1408ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
140908122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
141008122e43SStefano Zampini             if (eigs[j] == 0.0) {
1411ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
141208122e43SStefano Zampini             } else {
14139d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
1414ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
14159d54b7f4SStefano Zampini               } else {
14169d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
14179d54b7f4SStefano Zampini               }
1418fd14bc51SStefano Zampini             }
141908122e43SStefano Zampini           }
142008122e43SStefano Zampini         }
142108122e43SStefano Zampini       } else {
142208122e43SStefano Zampini           /* TODO */
142308122e43SStefano Zampini       }
1424aff50787SStefano Zampini     }
14256c3e6151SStefano Zampini     /* change the basis back to the original one */
14266c3e6151SStefano Zampini     if (sub_schurs->change) {
142772b8c272SStefano Zampini       Mat change,phi,phit;
14286c3e6151SStefano Zampini 
14296c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
14306c3e6151SStefano Zampini         PetscInt ii;
14316c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
14326c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
14336c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
14346c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
14356c3e6151SStefano Zampini           }
14366c3e6151SStefano Zampini         }
14376c3e6151SStefano Zampini       }
143872b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
14396c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
144072b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
14416c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
14426c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
14436c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
14446c3e6151SStefano Zampini     }
14458bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
14468bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
14479162d606SStefano Zampini     if (B_neigs) {
14489162d606SStefano 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);
1449fd14bc51SStefano Zampini 
1450fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
14519552c7c7SStefano Zampini         PetscInt ii;
14529552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1453ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
14549552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1455ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1456ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1457ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1458ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1459ac47001eSStefano Zampini #else
1460ac47001eSStefano 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);
1461ac47001eSStefano Zampini #endif
14629552c7c7SStefano Zampini           }
14639552c7c7SStefano Zampini         }
1464fd14bc51SStefano Zampini       }
14659162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
14669162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
14679162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
14689162d606SStefano Zampini       cum++;
146908122e43SStefano Zampini     }
147008122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
147108122e43SStefano Zampini     /* shift for next computation */
147208122e43SStefano Zampini     cumarray += subset_size*subset_size;
147308122e43SStefano Zampini   }
1474fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1475fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1476fd14bc51SStefano Zampini   }
147708122e43SStefano Zampini 
147808122e43SStefano Zampini   if (mss) {
147908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
148008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1481f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1482f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1483f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
148408122e43SStefano Zampini   }
1485f6f667cfSStefano Zampini   if (allocated_S_St) {
1486f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1487f6f667cfSStefano Zampini   }
1488f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
148908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
149008122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
149108122e43SStefano Zampini #endif
149208122e43SStefano Zampini   if (pcbddc->dbg_flag) {
14931b968477SStefano Zampini     PetscInt maxneigs_r;
1494b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
14959b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
149608122e43SStefano Zampini   }
149708122e43SStefano Zampini   PetscFunctionReturn(0);
149808122e43SStefano Zampini }
1499b1b3d7a2SStefano Zampini 
1500674ae819SStefano Zampini #undef __FUNCT__
1501c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1502c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1503c8587f34SStefano Zampini {
15048629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1505c8587f34SStefano Zampini   PetscErrorCode ierr;
1506c8587f34SStefano Zampini 
1507c8587f34SStefano Zampini   PetscFunctionBegin;
1508f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
15095e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1510c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1511c8587f34SStefano Zampini 
1512684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
15130fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1514684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1515c8587f34SStefano Zampini 
15168629588bSStefano Zampini   /*
15178629588bSStefano Zampini      Setup local correction and local part of coarse basis.
15188629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
15198629588bSStefano Zampini   */
152047f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
15218629588bSStefano Zampini 
15228629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
15238629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
15248629588bSStefano Zampini 
15258629588bSStefano Zampini   /* free */
15268629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1527c8587f34SStefano Zampini   PetscFunctionReturn(0);
1528c8587f34SStefano Zampini }
1529c8587f34SStefano Zampini 
1530c8587f34SStefano Zampini #undef __FUNCT__
1531674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1532674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1533674ae819SStefano Zampini {
1534674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1535674ae819SStefano Zampini   PetscErrorCode ierr;
1536674ae819SStefano Zampini 
1537674ae819SStefano Zampini   PetscFunctionBegin;
1538674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1539674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
154030368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1541674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1542785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1543674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1544f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1545f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1546785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
154763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
154863602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1549674ae819SStefano Zampini   PetscFunctionReturn(0);
1550674ae819SStefano Zampini }
1551674ae819SStefano Zampini 
1552674ae819SStefano Zampini #undef __FUNCT__
1553674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1554674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1555674ae819SStefano Zampini {
1556674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15574f1b2e48SStefano Zampini   PetscInt       i;
1558674ae819SStefano Zampini   PetscErrorCode ierr;
1559674ae819SStefano Zampini 
1560674ae819SStefano Zampini   PetscFunctionBegin;
1561b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1562674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
156316909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
15641dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
1565674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1566674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
15674f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
15684f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
15694f1b2e48SStefano Zampini   }
15704f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1571*b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
1572b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1573*b334f244SStefano Zampini   }
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);
1750*b334f244SStefano Zampini   } else if (sub_schurs && 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 
1908*b334f244SStefano Zampini     if (sub_schurs && 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);
233506656605SStefano Zampini     }
233616f15bc4SStefano Zampini     if (n_vertices && n_R) {
2337ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2338ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2339ffd830a3SStefano Zampini       PetscInt       n;
2340ffd830a3SStefano Zampini       PetscBool      flg_row;
234106656605SStefano Zampini 
2342ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2343af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
2344ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2345ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2346ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2347ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2348ffd830a3SStefano Zampini         PetscInt j;
2349ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2350ffd830a3SStefano Zampini       }
2351ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2352ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2353ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
235406656605SStefano Zampini     }
235506656605SStefano Zampini 
2356ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2357ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2358ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2359ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2360ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
236106656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
236206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
236306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
236406656605SStefano Zampini     }
2365ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2366ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2367ffd830a3SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2368ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2369ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2370ffd830a3SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2371ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2372ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
237306656605SStefano Zampini     }
2374ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
237506656605SStefano Zampini     /* coarse basis functions */
237606656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
237706656605SStefano Zampini       PetscScalar *y;
237806656605SStefano Zampini 
2379ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
238006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
238106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
238206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238406656605SStefano Zampini       if (i<n_vertices) {
238506656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
238606656605SStefano Zampini       }
238706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
238806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
238906656605SStefano Zampini 
239006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
239106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
239206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
239306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
239406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
239506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
239606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
239706656605SStefano Zampini       }
239806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
239906656605SStefano Zampini     }
2400ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2401ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
240206656605SStefano Zampini   }
2403d62866d3SStefano Zampini   /* free memory */
240488ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
240506656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
240606656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
240706656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
240806656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2409d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2410d62866d3SStefano Zampini   if (n_vertices) {
2411d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2412d62866d3SStefano Zampini   }
2413d62866d3SStefano Zampini   if (n_constraints) {
2414d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2415d62866d3SStefano Zampini   }
241688ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
241788ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
241888ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2419d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
242088ebb749SStefano Zampini     Mat         coarse_sub_mat;
242125084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
242288ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
242388ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
242488ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
24258bec7fa6SStefano Zampini     Mat         C_B,CPHI;
24268bec7fa6SStefano Zampini     IS          is_dummy;
24278bec7fa6SStefano Zampini     Vec         mones;
242888ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
242988ebb749SStefano Zampini     PetscReal   real_value;
243088ebb749SStefano Zampini 
2431a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2432a3df083aSStefano Zampini       Mat A;
2433a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2434a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2435a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2436a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2437a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2438a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2439a3df083aSStefano Zampini     } else {
244088ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
244188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
244288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
244388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2444a3df083aSStefano Zampini     }
244588ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
244688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2447ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
244888ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
244988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
245088ebb749SStefano Zampini     }
245188ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
245288ebb749SStefano Zampini 
245325084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
24543301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
245525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2456ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
245788ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
245888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
245988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
246088ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
246188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
246288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
246388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
246488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
246588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
246688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
246788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
246888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
246988ebb749SStefano Zampini     } else {
247088ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
247188ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
247288ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
247388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
247488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
247588ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
247688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
247788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
247888ebb749SStefano Zampini     }
247988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
248088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
248188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2482511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
24834f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2484fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
2485d12edf2fSStefano Zampini       PetscScalar *data,*data2;
24864f1b2e48SStefano Zampini       PetscInt    j;
2487d12edf2fSStefano Zampini 
24884f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2489fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
2490d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
249186c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2492d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2493d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
24944f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
24954f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2496d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
24974f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
24984f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
24994f1b2e48SStefano Zampini         }
2500d12edf2fSStefano Zampini       }
2501d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2502d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2503d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2504d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2505d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2506d12edf2fSStefano Zampini     }
2507d12edf2fSStefano Zampini #if 0
2508d12edf2fSStefano Zampini   {
2509d12edf2fSStefano Zampini     PetscViewer viewer;
2510d12edf2fSStefano Zampini     char filename[256];
2511ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2512d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2513d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2514ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2515ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2516ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2517d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
251872b8c272SStefano Zampini     if (save_change) {
251972b8c272SStefano Zampini       Mat phi_B;
252072b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
252172b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
252272b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
252372b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
252472b8c272SStefano Zampini     } else {
2525ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2526ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
252772b8c272SStefano Zampini     }
2528ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2529ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2530ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2531ffd830a3SStefano Zampini     }
2532ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2533ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2534ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2535ffd830a3SStefano Zampini     }
253672b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
2537ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2538ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2539ffd830a3SStefano Zampini     }
2540d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2541d12edf2fSStefano Zampini   }
2542d12edf2fSStefano Zampini #endif
254381d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
25448bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
25451575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
254606656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
25478bec7fa6SStefano Zampini 
25488bec7fa6SStefano Zampini     /* check constraints */
2549a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2550a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
25514f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
25528bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2553a00504b5SStefano Zampini     } else {
2554a00504b5SStefano Zampini       PetscScalar *data;
2555a00504b5SStefano Zampini       Mat         tmat;
2556a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2557a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
2558a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2559a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2560a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2561a00504b5SStefano Zampini     }
25628bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
25638bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
25648bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
25658bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2566bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2567ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
2568bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2569bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2570bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2571bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2572bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
257388ebb749SStefano Zampini     }
25748bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
25758bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
25768bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
25778bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
257825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
257988ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
258088ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
258188ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
258288ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
258388ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
258488ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
258588ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
258688ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
258788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
258888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2589ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
259088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
259188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
259288ebb749SStefano Zampini     }
259388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
259488ebb749SStefano Zampini   }
25958629588bSStefano Zampini   /* get back data */
25968629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
259788ebb749SStefano Zampini   PetscFunctionReturn(0);
259888ebb749SStefano Zampini }
259988ebb749SStefano Zampini 
260088ebb749SStefano Zampini #undef __FUNCT__
2601d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2602d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2603aa0d41d4SStefano Zampini {
2604d65f70fdSStefano Zampini   Mat            *work_mat;
2605d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2606d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2607c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
2608aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2609aa0d41d4SStefano Zampini 
2610aa0d41d4SStefano Zampini   PetscFunctionBegin;
2611d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2612d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2613d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2614d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2615aa0d41d4SStefano Zampini 
2616d65f70fdSStefano Zampini   if (!rsorted) {
2617906d46d4SStefano Zampini     const PetscInt *idxs;
2618906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2619aa0d41d4SStefano Zampini 
2620d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2621d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2622d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2623d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2624aa0d41d4SStefano Zampini     }
2625d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2626d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2627d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2628d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2629aa0d41d4SStefano Zampini     }
2630d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2631d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2632d65f70fdSStefano Zampini   } else {
2633d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2634d65f70fdSStefano Zampini     isrow_s = isrow;
2635aa0d41d4SStefano Zampini   }
2636906d46d4SStefano Zampini 
2637d65f70fdSStefano Zampini   if (!csorted) {
2638d65f70fdSStefano Zampini     if (isrow == iscol) {
2639d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2640d65f70fdSStefano Zampini       iscol_s = isrow_s;
2641d65f70fdSStefano Zampini     } else {
2642d65f70fdSStefano Zampini       const PetscInt *idxs;
2643d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
2644906d46d4SStefano Zampini 
2645d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2646d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2647d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2648d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2649d65f70fdSStefano Zampini       }
2650d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2651d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2652d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2653d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2654d65f70fdSStefano Zampini       }
2655d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2656d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2657d65f70fdSStefano Zampini     }
2658d65f70fdSStefano Zampini   } else {
2659d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2660d65f70fdSStefano Zampini     iscol_s = iscol;
2661d65f70fdSStefano Zampini   }
2662d65f70fdSStefano Zampini 
2663d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2664d65f70fdSStefano Zampini 
2665d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2666906d46d4SStefano Zampini     Mat      new_mat;
2667d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2668906d46d4SStefano Zampini 
2669d65f70fdSStefano Zampini     if (!rsorted) {
2670d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2671d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2672d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2673d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2674906d46d4SStefano Zampini       }
2675d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2676d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2677d65f70fdSStefano Zampini     } else {
2678d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2679906d46d4SStefano Zampini     }
2680d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2681d65f70fdSStefano Zampini 
2682d65f70fdSStefano Zampini     if (!csorted) {
2683d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2684d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2685d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2686d65f70fdSStefano Zampini       } else {
2687d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2688d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2689d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2690d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2691d65f70fdSStefano Zampini         }
2692d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2693d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2694d65f70fdSStefano Zampini       }
2695d65f70fdSStefano Zampini     } else {
2696d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2697d65f70fdSStefano Zampini     }
2698d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2699d65f70fdSStefano Zampini 
2700d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2701d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2702d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2703d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2704d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2705d65f70fdSStefano Zampini   }
2706d65f70fdSStefano Zampini 
2707d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2708d65f70fdSStefano Zampini   *B = work_mat[0];
2709d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2710d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2711d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2712d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2713d65f70fdSStefano Zampini }
2714d65f70fdSStefano Zampini 
2715d65f70fdSStefano Zampini #undef __FUNCT__
27165e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
27175e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2718aa0d41d4SStefano Zampini {
2719aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
27205e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2721d65f70fdSStefano Zampini   Mat            new_mat;
27225e8657edSStefano Zampini   IS             is_local,is_global;
2723d65f70fdSStefano Zampini   PetscInt       local_size;
2724d65f70fdSStefano Zampini   PetscBool      isseqaij;
2725aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2726aa0d41d4SStefano Zampini 
2727aa0d41d4SStefano Zampini   PetscFunctionBegin;
2728aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
27295e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
27305e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2731b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2732aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2733d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2734aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2735906d46d4SStefano Zampini 
2736906d46d4SStefano Zampini   /* check */
2737906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2738906d46d4SStefano Zampini     Vec       x,x_change;
2739906d46d4SStefano Zampini     PetscReal error;
2740906d46d4SStefano Zampini 
27415e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2742906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
27435e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2744e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2745e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2746d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2747e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2748e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2749906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2750906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2751906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2752906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2753906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2754906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2755906d46d4SStefano Zampini   }
2756906d46d4SStefano Zampini 
275722d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
27589b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
275922d5777bSStefano Zampini   if (isseqaij) {
2760a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2761a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2762aa0d41d4SStefano Zampini   } else {
2763a00504b5SStefano Zampini     Mat work_mat;
27641cf9b237SStefano Zampini 
2765a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2766aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2767a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
27681d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2769aa0d41d4SStefano Zampini   }
27703301b35fSStefano Zampini   if (matis->A->symmetric_set) {
27713301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2772e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
27733301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2774e496cd5dSStefano Zampini #endif
27753301b35fSStefano Zampini   }
2776d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2777aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2778aa0d41d4SStefano Zampini }
2779aa0d41d4SStefano Zampini 
2780aa0d41d4SStefano Zampini #undef __FUNCT__
2781a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
27828ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2783a64d13efSStefano Zampini {
2784a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2785a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2786d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
278753892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
27883a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
27893a50541eSStefano Zampini   PetscInt        vbs,bs;
27906816873aSStefano Zampini   PetscBT         bitmask=NULL;
2791a64d13efSStefano Zampini   PetscErrorCode  ierr;
2792a64d13efSStefano Zampini 
2793a64d13efSStefano Zampini   PetscFunctionBegin;
2794b23d619eSStefano Zampini   /*
2795b23d619eSStefano Zampini     No need to setup local scatters if
2796b23d619eSStefano Zampini       - primal space is unchanged
2797b23d619eSStefano Zampini         AND
2798b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2799b23d619eSStefano Zampini         AND
2800b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2801b23d619eSStefano Zampini   */
2802b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2803f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2804f4ddd8eeSStefano Zampini   }
2805f4ddd8eeSStefano Zampini   /* destroy old objects */
2806f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2807f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2808f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2809a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2810b371cd4fSStefano Zampini   n_B = pcis->n_B;
2811b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2812b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
28133a50541eSStefano Zampini 
2814a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
28156816873aSStefano Zampini 
281653892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2817*b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
2818854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2819a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2820a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
28210e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2822a64d13efSStefano Zampini     }
2823a64d13efSStefano Zampini 
2824a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
28254641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
28266816873aSStefano Zampini         idx_R_local[n_R++] = i;
2827a64d13efSStefano Zampini       }
2828a64d13efSStefano Zampini     }
2829df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2830df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
28316816873aSStefano Zampini 
2832df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2833df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
28346816873aSStefano Zampini   }
28353a50541eSStefano Zampini 
28363a50541eSStefano Zampini   /* Block code */
28373a50541eSStefano Zampini   vbs = 1;
28383a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
28393a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
28403a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
28413a50541eSStefano Zampini     PetscInt  *vary;
2842*b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
2843785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
28443a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2845d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2846d3df7717SStefano 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 */
28470e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2848d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
28493a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
28503a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
28513a50541eSStefano Zampini           break;
28523a50541eSStefano Zampini         }
28533a50541eSStefano Zampini       }
2854d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2855d3df7717SStefano Zampini     } else {
2856d3df7717SStefano Zampini       /* Verify directly the R set */
2857d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2858d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2859d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2860d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2861d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2862d3df7717SStefano Zampini             break;
2863d3df7717SStefano Zampini           }
2864d3df7717SStefano Zampini         }
2865d3df7717SStefano Zampini       }
2866d3df7717SStefano Zampini     }
28673a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
28683a50541eSStefano Zampini       vbs = bs;
28693a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
28703a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
28713a50541eSStefano Zampini       }
28723a50541eSStefano Zampini     }
28733a50541eSStefano Zampini   }
28743a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2875*b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
2876df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
287753892102SStefano Zampini 
2878df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2879df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
288053892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2881df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
288253892102SStefano Zampini   } else {
28833a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
288453892102SStefano Zampini   }
2885a64d13efSStefano Zampini 
2886a64d13efSStefano Zampini   /* print some info if requested */
2887a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2888a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2889a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
28901575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2891a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2892a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
28934f1b2e48SStefano 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);
2894a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2895a64d13efSStefano Zampini   }
2896a64d13efSStefano Zampini 
2897a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
2898*b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
28996816873aSStefano Zampini     IS       is_aux1,is_aux2;
29006816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
29016816873aSStefano Zampini 
29023a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2903854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2904854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2905a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
29064641a718SStefano Zampini     for (i=0; i<n_D; i++) {
29074641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
29084641a718SStefano Zampini     }
2909a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2910a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
29114641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
29124641a718SStefano Zampini         aux_array1[j++] = i;
2913a64d13efSStefano Zampini       }
2914a64d13efSStefano Zampini     }
2915a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2916a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2917a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
29184641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
29194641a718SStefano Zampini         aux_array2[j++] = i;
2920a64d13efSStefano Zampini       }
2921a64d13efSStefano Zampini     }
2922a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2923a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2924a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2925a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2926a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2927a64d13efSStefano Zampini 
29288eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2929785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2930a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
29314641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
29324641a718SStefano Zampini           aux_array1[j++] = i;
2933a64d13efSStefano Zampini         }
2934a64d13efSStefano Zampini       }
2935a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2936a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2937a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2938a64d13efSStefano Zampini     }
29394641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
29403a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2941d62866d3SStefano Zampini   } else {
2942df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
29436816873aSStefano Zampini     IS                 tis;
29446816873aSStefano Zampini     PetscInt           schur_size;
29456816873aSStefano Zampini 
2946df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
29476816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
2948df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
29496816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
29506816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
29516816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
29526816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
29536816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2954d62866d3SStefano Zampini     }
2955d62866d3SStefano Zampini   }
2956a64d13efSStefano Zampini   PetscFunctionReturn(0);
2957a64d13efSStefano Zampini }
2958a64d13efSStefano Zampini 
2959304d26faSStefano Zampini 
2960304d26faSStefano Zampini #undef __FUNCT__
2961304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2962684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2963304d26faSStefano Zampini {
2964304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2965304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2966304d26faSStefano Zampini   PC             pc_temp;
2967304d26faSStefano Zampini   Mat            A_RR;
2968f4ddd8eeSStefano Zampini   MatReuse       reuse;
2969304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2970304d26faSStefano Zampini   PetscReal      value;
297104708bb6SStefano Zampini   PetscInt       n_D,n_R;
2972c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
2973304d26faSStefano Zampini   PetscErrorCode ierr;
2974e604994aSStefano Zampini   /* prefixes stuff */
2975312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2976e604994aSStefano Zampini   size_t         len;
2977304d26faSStefano Zampini 
2978304d26faSStefano Zampini   PetscFunctionBegin;
2979304d26faSStefano Zampini 
2980e604994aSStefano Zampini   /* compute prefixes */
2981e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2982e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2983e604994aSStefano Zampini   if (!pcbddc->current_level) {
2984e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2985e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2986e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2987e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2988e604994aSStefano Zampini   } else {
2989e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2990312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2991e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2992e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2993312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2994312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
299534d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
299634d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2997e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2998e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2999e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
3000e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
3001e604994aSStefano Zampini   }
3002e604994aSStefano Zampini 
3003304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
3004684f6988SStefano Zampini   if (dirichlet) {
3005d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3006450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3007*b334f244SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) {
3008450f8f5eSStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
3009450f8f5eSStefano Zampini       }
3010450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
3011a3df083aSStefano Zampini         Mat    A_IIn;
3012a3df083aSStefano Zampini 
3013a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
3014a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
3015a3df083aSStefano Zampini         pcis->A_II = A_IIn;
3016a3df083aSStefano Zampini       }
3017450f8f5eSStefano Zampini     }
30183301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
30193301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
3020964fefecSStefano Zampini     }
3021ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
3022964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
3023304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
3024304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
3025304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
3026304d26faSStefano Zampini       /* default */
3027304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3028e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
30299577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3030304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
30319577ea80SStefano Zampini       if (issbaij) {
30329577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
30339577ea80SStefano Zampini       } else {
3034304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
30359577ea80SStefano Zampini       }
3036304d26faSStefano Zampini       /* Allow user's customization */
3037304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3038304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3039304d26faSStefano Zampini     }
3040d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
3041*b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3042df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3043d62866d3SStefano Zampini 
3044df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
3045d5574798SStefano Zampini     }
3046304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3047304d26faSStefano Zampini     if (!n_D) {
3048304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
3049304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3050304d26faSStefano Zampini     }
3051304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
3052304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
3053304d26faSStefano Zampini     /* set ksp_D into pcis data */
3054304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
3055304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
3056304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
3057684f6988SStefano Zampini   }
3058304d26faSStefano Zampini 
3059304d26faSStefano Zampini   /* NEUMANN PROBLEM */
3060684f6988SStefano Zampini   A_RR = 0;
3061684f6988SStefano Zampini   if (neumann) {
3062d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
306304708bb6SStefano Zampini     PetscInt        ibs,mbs;
306404708bb6SStefano Zampini     PetscBool       issbaij;
306504708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
3066f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
30678ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
3068f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
3069f4ddd8eeSStefano Zampini       PetscInt nn_R;
307081d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
3071f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3072f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
3073f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
3074f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
3075f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3076f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3077f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
3078727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
3079f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3080f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
3081f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
3082f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
3083f4ddd8eeSStefano Zampini         }
3084f4ddd8eeSStefano Zampini       }
3085f4ddd8eeSStefano Zampini       /* last check */
3086d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
3087f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3088f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3089f4ddd8eeSStefano Zampini       }
3090f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
3091f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
3092f4ddd8eeSStefano Zampini     }
3093a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
3094af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3095af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
309604708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
309704708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
309804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
309904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
310004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
3101af732b37SStefano Zampini       } else {
3102511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
31036816873aSStefano Zampini       }
310404708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
310504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
310604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
310704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
310804708bb6SStefano Zampini       } else {
3109511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
311004708bb6SStefano Zampini       }
311104708bb6SStefano Zampini     }
3112a00504b5SStefano Zampini     /* extract A_RR */
3113*b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3114a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3115a00504b5SStefano Zampini 
3116a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
311716e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3118a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
311916e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
312016e386b8SStefano Zampini         } else {
3121a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
3122a00504b5SStefano Zampini         }
3123a00504b5SStefano Zampini       } else {
3124a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3125a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
3126a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3127a00504b5SStefano Zampini       }
3128a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
3129f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
313016e386b8SStefano Zampini     }
31313301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
31323301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
31336816873aSStefano Zampini     }
3134f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
3135304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
3136304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
3137304d26faSStefano Zampini       /* default */
3138304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3139e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
3140304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
31419577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
31429577ea80SStefano Zampini       if (issbaij) {
31439577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
31449577ea80SStefano Zampini       } else {
3145304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
31469577ea80SStefano Zampini       }
3147304d26faSStefano Zampini       /* Allow user's customization */
3148304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3149304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3150304d26faSStefano Zampini     }
3151304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3152304d26faSStefano Zampini     if (!n_R) {
3153304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
3154304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3155304d26faSStefano Zampini     }
31565cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
3157df4d28bfSStefano Zampini     /* Reuse solver if it is present */
3158*b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3159df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3160d62866d3SStefano Zampini 
3161df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
3162d62866d3SStefano Zampini     }
3163304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
3164304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
3165684f6988SStefano Zampini   }
3166304d26faSStefano Zampini 
3167684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
3168684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
31691575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3170684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3171684f6988SStefano Zampini   }
3172c7017625SStefano Zampini 
3173c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
3174c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
3175c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
3176c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
3177c7017625SStefano Zampini   }
3178c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
3179c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
3180c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
3181c7017625SStefano Zampini   }
3182c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
3183c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
3184c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
3185c7017625SStefano Zampini   }
3186c7017625SStefano Zampini 
3187c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
3188c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
3189684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
31900fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
31910fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
31920fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
31930fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
31940fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
3195e604994aSStefano 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);
3196c7017625SStefano Zampini       if (check_corr[0]) {
3197c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
3198c7017625SStefano Zampini       }
3199304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3200304d26faSStefano Zampini     }
3201684f6988SStefano Zampini     if (neumann) { /* Neumann */
32020fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
32030fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
32040fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
32050fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
32060fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
3207e604994aSStefano 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);
3208c7017625SStefano Zampini       if (check_corr[1]) {
3209c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
3210c7017625SStefano Zampini       }
3211304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3212304d26faSStefano Zampini     }
3213684f6988SStefano Zampini   }
32145cbda25cSStefano Zampini   /* free Neumann problem's matrix */
32155cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3216304d26faSStefano Zampini   PetscFunctionReturn(0);
3217304d26faSStefano Zampini }
3218304d26faSStefano Zampini 
3219304d26faSStefano Zampini #undef __FUNCT__
3220ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
322180677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
3222674ae819SStefano Zampini {
3223674ae819SStefano Zampini   PetscErrorCode  ierr;
3224674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3225be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3226*b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
3227674ae819SStefano Zampini 
3228674ae819SStefano Zampini   PetscFunctionBegin;
3229*b334f244SStefano Zampini   if (!reuse_solver) {
323080677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
323120c7b377SStefano Zampini   }
323280677318SStefano Zampini   if (!pcbddc->switch_static) {
323380677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
323480677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
323580677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
323620c7b377SStefano Zampini     }
3237*b334f244SStefano Zampini     if (!reuse_solver) {
323880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
323980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
324020c7b377SStefano Zampini     } else {
3241df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3242be83ff47SStefano Zampini 
3243df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3244df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
324520c7b377SStefano Zampini     }
3246be83ff47SStefano Zampini   } else {
324780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
324880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
324980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
325080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
325180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
325280677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
325380677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
325480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
325580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3256674ae819SStefano Zampini     }
3257674ae819SStefano Zampini   }
3258*b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
325980677318SStefano Zampini     if (applytranspose) {
326080677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
326180677318SStefano Zampini     } else {
326280677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
326380677318SStefano Zampini     }
3264be83ff47SStefano Zampini   } else {
3265df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3266be83ff47SStefano Zampini 
3267be83ff47SStefano Zampini     if (applytranspose) {
3268df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3269be83ff47SStefano Zampini     } else {
3270df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3271be83ff47SStefano Zampini     }
3272be83ff47SStefano Zampini   }
327380677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
327480677318SStefano Zampini   if (!pcbddc->switch_static) {
3275*b334f244SStefano Zampini     if (!reuse_solver) {
327680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
327780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3278be83ff47SStefano Zampini     } else {
3279df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3280be83ff47SStefano Zampini 
3281df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3282df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3283be83ff47SStefano Zampini     }
328480677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
328580677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
328680677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
328780677318SStefano Zampini     }
328880677318SStefano Zampini   } else {
328980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
329080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
329180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
329280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
329380677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
329480677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
329580677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
329680677318SStefano Zampini     }
329780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
329880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
329980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
330080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3301674ae819SStefano Zampini   }
3302674ae819SStefano Zampini   PetscFunctionReturn(0);
3303674ae819SStefano Zampini }
3304674ae819SStefano Zampini 
3305dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
3306674ae819SStefano Zampini #undef __FUNCT__
3307674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
3308dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
3309674ae819SStefano Zampini {
3310674ae819SStefano Zampini   PetscErrorCode ierr;
3311674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3312674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
3313674ae819SStefano Zampini   const PetscScalar zero = 0.0;
3314674ae819SStefano Zampini 
3315674ae819SStefano Zampini   PetscFunctionBegin;
3316dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
33174fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3318dc359a40SStefano Zampini     if (applytranspose) {
3319674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
33208eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3321dc359a40SStefano Zampini     } else {
3322674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3323674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
332415aaf578SStefano Zampini     }
33254fee134fSStefano Zampini   } else {
33264fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
33274fee134fSStefano Zampini   }
3328efc2fbd9SStefano Zampini 
3329efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
33304f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
3331efc2fbd9SStefano Zampini     PetscScalar *array;
33324f1b2e48SStefano Zampini     PetscInt    j;
3333efc2fbd9SStefano Zampini 
3334efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
33354f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
3336efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3337efc2fbd9SStefano Zampini   }
3338efc2fbd9SStefano Zampini 
333912edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
334012edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
334112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
334212edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
334312edc857SStefano Zampini 
33449f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
334512edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
334651694757SStefano Zampini     Mat          coarse_mat;
3347964fefecSStefano Zampini     Vec          rhs,sol;
334851694757SStefano Zampini     MatNullSpace nullsp;
334927b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
3350964fefecSStefano Zampini 
335127b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
335227b6a85dSStefano Zampini       PC        coarse_pc;
335327b6a85dSStefano Zampini 
335427b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
335527b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
335627b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
335727b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
335827b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
335927b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
33603bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
336127b6a85dSStefano Zampini       }
336227b6a85dSStefano Zampini     }
3363964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3364964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
336551694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
336651694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
336751694757SStefano Zampini     if (nullsp) {
336851694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
336951694757SStefano Zampini     }
337012edc857SStefano Zampini     if (applytranspose) {
33711f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only) {
33721f4df5f7SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
33732701bc32SStefano Zampini       } else {
3374964fefecSStefano Zampini         ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
33752701bc32SStefano Zampini       }
33762701bc32SStefano Zampini     } else {
33771f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
33782701bc32SStefano Zampini         PC        coarse_pc;
33792701bc32SStefano Zampini 
33802701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
33812701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
33823e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
33832701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
338412edc857SStefano Zampini       } else {
3385964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
338612edc857SStefano Zampini       }
33872701bc32SStefano Zampini     }
33881d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
338927b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
339027b6a85dSStefano Zampini       PC        coarse_pc;
339127b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
339227b6a85dSStefano Zampini 
339327b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
339427b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
339527b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
33963bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
339727b6a85dSStefano Zampini     }
339851694757SStefano Zampini     if (nullsp) {
339951694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
340051694757SStefano Zampini     }
340112edc857SStefano Zampini   }
3402674ae819SStefano Zampini 
3403674ae819SStefano Zampini   /* Local solution on R nodes */
34044fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
340580677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
34069f00e9b4SStefano Zampini   }
34079f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
34089f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
340912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3410674ae819SStefano Zampini 
34114fee134fSStefano Zampini   /* Sum contributions from the two levels */
34124fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3413dc359a40SStefano Zampini     if (applytranspose) {
3414dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3415dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3416dc359a40SStefano Zampini     } else {
3417674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
34188eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3419dc359a40SStefano Zampini     }
3420efc2fbd9SStefano Zampini     /* store p0 */
34214f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3422efc2fbd9SStefano Zampini       PetscScalar *array;
34234f1b2e48SStefano Zampini       PetscInt    j;
3424efc2fbd9SStefano Zampini 
3425efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
34264f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3427efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3428efc2fbd9SStefano Zampini     }
34294fee134fSStefano Zampini   } else { /* expand the coarse solution */
34304fee134fSStefano Zampini     if (applytranspose) {
34314fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
34324fee134fSStefano Zampini     } else {
34334fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
34344fee134fSStefano Zampini     }
34354fee134fSStefano Zampini   }
3436674ae819SStefano Zampini   PetscFunctionReturn(0);
3437674ae819SStefano Zampini }
3438674ae819SStefano Zampini 
3439674ae819SStefano Zampini #undef __FUNCT__
3440674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
344112edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3442674ae819SStefano Zampini {
3443674ae819SStefano Zampini   PetscErrorCode ierr;
3444674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
344558da7f69SStefano Zampini   PetscScalar    *array;
344612edc857SStefano Zampini   Vec            from,to;
3447674ae819SStefano Zampini 
3448674ae819SStefano Zampini   PetscFunctionBegin;
344912edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
345012edc857SStefano Zampini     from = pcbddc->coarse_vec;
345112edc857SStefano Zampini     to = pcbddc->vec1_P;
345212edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
345312edc857SStefano Zampini       Vec tvec;
345458da7f69SStefano Zampini 
345558da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
345658da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
345712edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
345858da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
345958da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
346058da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
346112edc857SStefano Zampini     }
346212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
346312edc857SStefano Zampini     from = pcbddc->vec1_P;
346412edc857SStefano Zampini     to = pcbddc->coarse_vec;
346512edc857SStefano Zampini   }
346612edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3467674ae819SStefano Zampini   PetscFunctionReturn(0);
3468674ae819SStefano Zampini }
3469674ae819SStefano Zampini 
3470674ae819SStefano Zampini #undef __FUNCT__
3471674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
347212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3473674ae819SStefano Zampini {
3474674ae819SStefano Zampini   PetscErrorCode ierr;
3475674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
347658da7f69SStefano Zampini   PetscScalar    *array;
347712edc857SStefano Zampini   Vec            from,to;
3478674ae819SStefano Zampini 
3479674ae819SStefano Zampini   PetscFunctionBegin;
348012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
348112edc857SStefano Zampini     from = pcbddc->coarse_vec;
348212edc857SStefano Zampini     to = pcbddc->vec1_P;
348312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
348412edc857SStefano Zampini     from = pcbddc->vec1_P;
348512edc857SStefano Zampini     to = pcbddc->coarse_vec;
348612edc857SStefano Zampini   }
348712edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
348812edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
348912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
349012edc857SStefano Zampini       Vec tvec;
349158da7f69SStefano Zampini 
349212edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
349358da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
349458da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
349558da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
349658da7f69SStefano Zampini     }
349758da7f69SStefano Zampini   } else {
349858da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
349958da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
350012edc857SStefano Zampini     }
350112edc857SStefano Zampini   }
3502674ae819SStefano Zampini   PetscFunctionReturn(0);
3503674ae819SStefano Zampini }
3504674ae819SStefano Zampini 
3505984c4197SStefano Zampini /* uncomment for testing purposes */
3506984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3507674ae819SStefano Zampini #undef __FUNCT__
3508674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3509674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3510674ae819SStefano Zampini {
3511674ae819SStefano Zampini   PetscErrorCode    ierr;
3512674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3513674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3514674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3515984c4197SStefano Zampini   /* one and zero */
3516984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3517984c4197SStefano Zampini   /* space to store constraints and their local indices */
35189162d606SStefano Zampini   PetscScalar       *constraints_data;
35199162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
35209162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
35219162d606SStefano Zampini   PetscInt          *constraints_n;
3522984c4197SStefano Zampini   /* iterators */
3523b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3524984c4197SStefano Zampini   /* BLAS integers */
3525e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3526e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3527c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3528727cdba6SStefano Zampini   /* reuse */
35290e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
35300e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3531984c4197SStefano Zampini   /* change of basis */
3532b3d85658SStefano Zampini   PetscBool         qr_needed;
35339162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3534984c4197SStefano Zampini   /* auxiliary stuff */
353564efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
35368a0068c3SStefano Zampini   PetscInt          ncc;
3537984c4197SStefano Zampini   /* some quantities */
353845a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3539a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3540984c4197SStefano Zampini 
3541674ae819SStefano Zampini   PetscFunctionBegin;
35428e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
35438e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
35448e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
354516909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
3546088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3547088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
35480e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
35490e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
35500e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
35510e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
35520e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3553088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3554cf5a6209SStefano Zampini 
3555cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
35569162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3557cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3558cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3559cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3560cf5a6209SStefano Zampini     PetscScalar  *array;
3561cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3562cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3563674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3564b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3565674ae819SStefano Zampini     PetscScalar  *work;
3566674ae819SStefano Zampini     PetscReal    *singular_vals;
3567674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3568674ae819SStefano Zampini     PetscReal    *rwork;
3569674ae819SStefano Zampini #endif
3570674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3571674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3572674ae819SStefano Zampini #else
3573964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3574964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3575674ae819SStefano Zampini #endif
3576674ae819SStefano Zampini 
3577674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3578d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3579e4d548c7SStefano Zampini     /* print some info */
35801f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
3581e4d548c7SStefano Zampini       PetscInt nv;
3582e4d548c7SStefano Zampini 
3583e4d548c7SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
3584e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
3585e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3586e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3587e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3588e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
3589e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
3590e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3591e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3592e4d548c7SStefano Zampini     }
3593e4d548c7SStefano Zampini 
3594d06fc5fdSStefano Zampini     /* free unneeded index sets */
3595d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3596d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3597674ae819SStefano Zampini     }
3598d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3599d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3600d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3601d06fc5fdSStefano Zampini       }
3602d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3603d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3604d06fc5fdSStefano Zampini     }
3605d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3606d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3607d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3608d06fc5fdSStefano Zampini       }
3609d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3610d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3611d06fc5fdSStefano Zampini     }
361270022509SStefano Zampini 
3613674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3614674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3615674ae819SStefano Zampini     if (nearnullsp) {
3616674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3617f4ddd8eeSStefano Zampini       /* remove any stored info */
3618f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3619f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3620f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3621f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3622f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3623473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3624f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3625f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3626f4ddd8eeSStefano Zampini       }
3627984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3628984c4197SStefano Zampini       nnsp_size = 0;
3629674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3630674ae819SStefano Zampini     }
3631984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3632984c4197SStefano Zampini     max_constraints = nnsp_size;
3633984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3634984c4197SStefano Zampini 
3635674ae819SStefano Zampini     /*
3636674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
36379162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
36389162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
36399162d606SStefano Zampini          There can be multiple constraints per connected component
3640674ae819SStefano Zampini                                                                                                                                                            */
3641674ae819SStefano Zampini     n_vertices = 0;
3642674ae819SStefano Zampini     if (ISForVertices) {
3643674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3644674ae819SStefano Zampini     }
36459162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
36469162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
36479162d606SStefano Zampini 
36489162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
36499162d606SStefano Zampini     total_counts *= max_constraints;
3650674ae819SStefano Zampini     total_counts += n_vertices;
36514641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
36529162d606SStefano Zampini 
3653674ae819SStefano Zampini     total_counts = 0;
3654674ae819SStefano Zampini     max_size_of_constraint = 0;
3655674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
36569162d606SStefano Zampini       IS used_is;
3657674ae819SStefano Zampini       if (i<n_ISForEdges) {
36589162d606SStefano Zampini         used_is = ISForEdges[i];
3659674ae819SStefano Zampini       } else {
36609162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3661674ae819SStefano Zampini       }
36629162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3663674ae819SStefano Zampini       total_counts += j;
3664674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3665674ae819SStefano Zampini     }
36669162d606SStefano 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);
36679162d606SStefano Zampini 
3668984c4197SStefano Zampini     /* get local part of global near null space vectors */
3669785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3670984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3671984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3672e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3673e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3674984c4197SStefano Zampini     }
3675674ae819SStefano Zampini 
3676242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3677242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3678a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3679242a89d7SStefano Zampini 
3680984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3681a773dcb8SStefano Zampini     if (!skip_lapack) {
3682674ae819SStefano Zampini       PetscScalar temp_work;
3683911cabfeSStefano Zampini 
3684674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3685984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3686785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3687785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3688785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3689674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3690785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3691674ae819SStefano Zampini #endif
3692674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3693c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3694c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3695674ae819SStefano Zampini       lwork = -1;
3696674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3697674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3698c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3699674ae819SStefano Zampini #else
3700c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3701674ae819SStefano Zampini #endif
3702674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3703984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3704674ae819SStefano Zampini #else /* on missing GESVD */
3705674ae819SStefano Zampini       /* SVD */
3706674ae819SStefano Zampini       PetscInt max_n,min_n;
3707674ae819SStefano Zampini       max_n = max_size_of_constraint;
3708984c4197SStefano Zampini       min_n = max_constraints;
3709984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3710674ae819SStefano Zampini         min_n = max_size_of_constraint;
3711984c4197SStefano Zampini         max_n = max_constraints;
3712674ae819SStefano Zampini       }
3713785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3714674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3715785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3716674ae819SStefano Zampini #endif
3717674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3718674ae819SStefano Zampini       lwork = -1;
3719e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3720e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3721b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3722674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3723674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
37249162d606SStefano 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));
3725674ae819SStefano Zampini #else
37269162d606SStefano 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));
3727674ae819SStefano Zampini #endif
3728674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3729984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3730984c4197SStefano Zampini #endif /* on missing GESVD */
3731674ae819SStefano Zampini       /* Allocate optimal workspace */
3732674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3733854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3734674ae819SStefano Zampini     }
3735674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3736674ae819SStefano Zampini     total_counts = 0;
37379162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
37389162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3739674ae819SStefano Zampini     /* vertices */
37409162d606SStefano Zampini     if (n_vertices) {
3741674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
37429162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3743674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
37449162d606SStefano Zampini         constraints_n[total_counts] = 1;
37459162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
37469162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
37479162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3748674ae819SStefano Zampini         total_counts++;
3749674ae819SStefano Zampini       }
3750674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3751674ae819SStefano Zampini       n_vertices = total_counts;
3752674ae819SStefano Zampini     }
3753984c4197SStefano Zampini 
3754674ae819SStefano Zampini     /* edges and faces */
37559162d606SStefano Zampini     total_counts_cc = total_counts;
3756911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
37579162d606SStefano Zampini       IS        used_is;
37589162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
37599162d606SStefano Zampini 
3760911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
37619162d606SStefano Zampini         used_is = ISForEdges[ncc];
3762984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3763674ae819SStefano Zampini       } else {
37649162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3765984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3766674ae819SStefano Zampini       }
3767674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
37689162d606SStefano Zampini 
37699162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
37709162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3771984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3772984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3773674ae819SStefano Zampini       if (nnsp_has_cnst) {
37745b08dc53SStefano Zampini         PetscScalar quad_value;
37759162d606SStefano Zampini 
37769162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
37779162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
37789162d606SStefano Zampini 
3779a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3780674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3781a773dcb8SStefano Zampini         } else {
3782a773dcb8SStefano Zampini           quad_value = 1.0;
3783a773dcb8SStefano Zampini         }
3784674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
37859162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3786674ae819SStefano Zampini         }
37879162d606SStefano Zampini         temp_constraints++;
3788674ae819SStefano Zampini         total_counts++;
3789674ae819SStefano Zampini       }
3790674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3791984c4197SStefano Zampini         PetscReal real_value;
37929162d606SStefano Zampini         PetscScalar *ptr_to_data;
37939162d606SStefano Zampini 
3794984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
37959162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3796674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
37979162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3798674ae819SStefano Zampini         }
3799984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3800984c4197SStefano Zampini         /* check if array is null on the connected component */
3801e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
38029162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
38035b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3804674ae819SStefano Zampini           temp_constraints++;
3805674ae819SStefano Zampini           total_counts++;
38069162d606SStefano Zampini           if (!idxs_copied) {
38079162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
38089162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3809674ae819SStefano Zampini           }
3810674ae819SStefano Zampini         }
38119162d606SStefano Zampini       }
38129162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
381345a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3814eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3815a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
38169162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
38179162d606SStefano Zampini 
38189162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3819a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
38209162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3821a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
38229162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3823a773dcb8SStefano Zampini         } else { /* perform SVD */
3824984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
38259162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3826674ae819SStefano Zampini 
3827674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3828984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3829984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3830984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3831984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3832984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3833984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3834984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3835984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3836674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3837e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3838984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3839674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3840674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
38419162d606SStefano 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));
3842674ae819SStefano Zampini             }
3843674ae819SStefano Zampini           }
3844e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3845e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3846e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3847674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3848c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3849674ae819SStefano Zampini #else
3850c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3851674ae819SStefano Zampini #endif
3852674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3853984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3854984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3855674ae819SStefano Zampini           j = 0;
3856984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3857674ae819SStefano Zampini           total_counts = total_counts-j;
385845a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3859e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3860c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3861c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3862c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3863c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3864c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3865c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3866674ae819SStefano Zampini           if (j<temp_constraints) {
3867984c4197SStefano Zampini             PetscInt ii;
3868984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3869674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38709162d606SStefano 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));
3871674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3872984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3873674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
38749162d606SStefano 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];
3875674ae819SStefano Zampini               }
3876674ae819SStefano Zampini             }
3877674ae819SStefano Zampini           }
3878674ae819SStefano Zampini #else  /* on missing GESVD */
3879e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3880e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3881b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3882674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3883674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
38849162d606SStefano 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));
3885674ae819SStefano Zampini #else
38869162d606SStefano 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));
3887674ae819SStefano Zampini #endif
3888984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3889674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3890984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3891e310c8b4SStefano Zampini           k = temp_constraints;
3892e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3893674ae819SStefano Zampini           j = 0;
3894e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
389545a1bb75SStefano Zampini           valid_constraints = k-j;
3896911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3897984c4197SStefano Zampini #endif /* on missing GESVD */
3898674ae819SStefano Zampini         }
3899a773dcb8SStefano Zampini       }
39009162d606SStefano Zampini       /* update pointers information */
39019162d606SStefano Zampini       if (valid_constraints) {
39029162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
39039162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
39049162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
39059162d606SStefano Zampini         /* set change_of_basis flag */
390645a1bb75SStefano Zampini         if (boolforchange) {
3907b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
39089162d606SStefano Zampini         }
3909b3d85658SStefano Zampini         total_counts_cc++;
391045a1bb75SStefano Zampini       }
391145a1bb75SStefano Zampini     }
3912984c4197SStefano Zampini     /* free workspace */
39138f1c130eSStefano Zampini     if (!skip_lapack) {
3914984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3915984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3916984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3917984c4197SStefano Zampini #endif
3918984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3919984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3920984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3921984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3922984c4197SStefano Zampini #endif
3923984c4197SStefano Zampini     }
3924984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3925984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3926984c4197SStefano Zampini     }
3927984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3928cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3929cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3930cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3931cf5a6209SStefano Zampini     }
3932cf5a6209SStefano Zampini     if (n_ISForFaces) {
3933cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3934cf5a6209SStefano Zampini     }
3935cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3936cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3937cf5a6209SStefano Zampini     }
3938cf5a6209SStefano Zampini     if (n_ISForEdges) {
3939cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3940cf5a6209SStefano Zampini     }
3941cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
394208122e43SStefano Zampini   } else {
394308122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3944984c4197SStefano Zampini 
394508122e43SStefano Zampini     total_counts = 0;
394608122e43SStefano Zampini     n_vertices = 0;
3947d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3948d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
394908122e43SStefano Zampini     }
395008122e43SStefano Zampini     max_constraints = 0;
39519162d606SStefano Zampini     total_counts_cc = 0;
395208122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
395308122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
39549162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
395508122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
395608122e43SStefano Zampini     }
39579162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
39589162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
39599162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
39609162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
396174d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
39629162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
39639162d606SStefano Zampini     total_counts_cc = 0;
39649162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
39659162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
39669162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
396708122e43SStefano Zampini       }
396808122e43SStefano Zampini     }
39699162d606SStefano Zampini #if 0
39709162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
39719162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
39729162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
39739162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
39749162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
39759162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
39769162d606SStefano Zampini       }
39779162d606SStefano Zampini       printf("\n");
39789162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
39799162d606SStefano Zampini     }
39801b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
39818bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
39821b968477SStefano Zampini     }
39831b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
39848bec7fa6SStefano 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]);
39851b968477SStefano Zampini     }
398608122e43SStefano Zampini #endif
398708122e43SStefano Zampini 
39888bec7fa6SStefano Zampini     max_size_of_constraint = 0;
39899162d606SStefano 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]);
39909162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
399108122e43SStefano Zampini     /* Change of basis */
3992b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
399308122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
399408122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
399508122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3996b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
399708122e43SStefano Zampini         }
399808122e43SStefano Zampini       }
399908122e43SStefano Zampini     }
400008122e43SStefano Zampini   }
4001984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
40024f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
400308122e43SStefano Zampini 
40049162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
40059162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
40066c4ed002SBarry 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);
4007674ae819SStefano Zampini 
4008674ae819SStefano Zampini   /* Create constraint matrix */
4009674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
401016f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
4011984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
4012984c4197SStefano Zampini 
4013984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
4014a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
4015a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
401674d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
4017984c4197SStefano Zampini   total_primal_vertices=0;
4018b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
40199162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
40209162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
402172b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
40229162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
4023b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
402464efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
40259162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
40269162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
4027a717540cSStefano Zampini       }
4028b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
402991af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
4030a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
4031a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
4032a717540cSStefano Zampini       }
4033fa434743SStefano Zampini     } else {
4034b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
4035fa434743SStefano Zampini     }
4036a717540cSStefano Zampini   }
4037b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
4038b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
4039674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
404070022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4041b3d85658SStefano Zampini 
40424f1b2e48SStefano 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);
40430e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
40440e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
4045984c4197SStefano Zampini 
4046984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
404774d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
4048785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
4049984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
405074d5cdf7SStefano Zampini 
4051984c4197SStefano Zampini   j = total_primal_vertices;
405274d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
4053b3d85658SStefano Zampini   cum = total_primal_vertices;
40549162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
40554641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
4056b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
4057b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
4058b3d85658SStefano Zampini       cum++;
40599162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
406074d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
406174d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
406274d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
406374d5cdf7SStefano Zampini       }
40649162d606SStefano Zampini       j += constraints_n[i];
4065674ae819SStefano Zampini     }
4066674ae819SStefano Zampini   }
4067674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
4068674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
4069088faed8SStefano Zampini 
4070674ae819SStefano Zampini   /* set values in constraint matrix */
4071984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
40720e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4073674ae819SStefano Zampini   }
4074984c4197SStefano Zampini   total_counts = total_primal_vertices;
40759162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
40764641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
40779162d606SStefano Zampini       PetscInt *cols;
40789162d606SStefano Zampini 
40799162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
40809162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
40819162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
40829162d606SStefano Zampini         PetscInt    row = total_counts+k;
40839162d606SStefano Zampini         PetscScalar *vals;
40849162d606SStefano Zampini 
40859162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
40869162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
40879162d606SStefano Zampini       }
40889162d606SStefano Zampini       total_counts += constraints_n[i];
4089674ae819SStefano Zampini     }
4090674ae819SStefano Zampini   }
4091674ae819SStefano Zampini   /* assembling */
4092674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4093674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4094088faed8SStefano Zampini 
4095984c4197SStefano Zampini   /*
40966a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4097984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
4098f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
4099984c4197SStefano Zampini   */
4100674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
4101674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
4102026de310SStefano Zampini     /* dual and primal dofs on a single cc */
4103984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
4104984c4197SStefano Zampini     /* working stuff for GEQRF */
410581d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
4106984c4197SStefano Zampini     PetscBLASInt lqr_work;
4107984c4197SStefano Zampini     /* working stuff for UNGQR */
4108984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
4109984c4197SStefano Zampini     PetscBLASInt lgqr_work;
4110984c4197SStefano Zampini     /* working stuff for TRTRS */
4111984c4197SStefano Zampini     PetscScalar  *trs_rhs;
41123f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
4113984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
4114984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
4115984c4197SStefano Zampini     PetscScalar  *start_vals;
4116984c4197SStefano Zampini     /* working stuff for values insertion */
41174641a718SStefano Zampini     PetscBT      is_primal;
411864efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
4119906d46d4SStefano Zampini     /* matrix sizes */
4120906d46d4SStefano Zampini     PetscInt     global_size,local_size;
4121906d46d4SStefano Zampini     /* temporary change of basis */
4122906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
4123cf5a6209SStefano Zampini     /* extra space for debugging */
4124cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
4125984c4197SStefano Zampini 
4126906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
4127906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
412816f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
4129bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
4130906d46d4SStefano Zampini     /* nonzeros for local mat */
4131bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
41321dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4133bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
41341dd7afcfSStefano Zampini     } else {
41351dd7afcfSStefano Zampini       const PetscInt *ii;
41361dd7afcfSStefano Zampini       PetscInt       n;
41371dd7afcfSStefano Zampini       PetscBool      flg_row;
41381dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
41391dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
41401dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
41411dd7afcfSStefano Zampini     }
41429162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
4143a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
41449162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
4145a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
41469162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
4147a717540cSStefano Zampini         } else {
41489162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
41499162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
4150a717540cSStefano Zampini         }
4151a717540cSStefano Zampini       }
4152a717540cSStefano Zampini     }
4153906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
4154bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
41551dd7afcfSStefano Zampini     /* Set interior change in the matrix */
41561dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4157bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
4158906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
4159a717540cSStefano Zampini       }
41601dd7afcfSStefano Zampini     } else {
41611dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
41621dd7afcfSStefano Zampini       PetscScalar    *aa;
41631dd7afcfSStefano Zampini       PetscInt       n;
41641dd7afcfSStefano Zampini       PetscBool      flg_row;
41651dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
41661dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
41671dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
41681dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
41691dd7afcfSStefano Zampini       }
41701dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
41711dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
41721dd7afcfSStefano Zampini     }
4173a717540cSStefano Zampini 
4174a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
4175a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4176a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4177a717540cSStefano Zampini     }
4178a717540cSStefano Zampini 
4179a717540cSStefano Zampini 
4180a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
4181a717540cSStefano Zampini     /*
4182a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
4183a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
4184a717540cSStefano Zampini 
4185a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
4186a717540cSStefano Zampini 
4187a6b551f4SStefano 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)
4188a6b551f4SStefano Zampini 
4189a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
4190a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
4191a717540cSStefano Zampini             |              ...                        |
4192a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
4193a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
4194a717540cSStefano Zampini 
4195a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
4196a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
4197a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
4198a6b551f4SStefano Zampini 
4199a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
4200a717540cSStefano Zampini     */
4201a717540cSStefano Zampini     if (qr_needed) {
4202984c4197SStefano Zampini       /* space to store Q */
4203854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
4204984c4197SStefano Zampini       /* first we issue queries for optimal work */
42053f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
42063f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
42073f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4208984c4197SStefano Zampini       lqr_work = -1;
42093f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
4210984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
4211984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
4212785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
4213984c4197SStefano Zampini       lgqr_work = -1;
42143f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
42153f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
42163f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
42173f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
42183f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
42193f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
4220984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
4221984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
4222785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
4223984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
4224785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
4225984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
4226785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
4227a717540cSStefano Zampini       /* allocating workspace for check */
4228a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
4229cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
4230a717540cSStefano Zampini       }
4231a717540cSStefano Zampini     }
4232984c4197SStefano Zampini     /* array to store whether a node is primal or not */
42334641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
4234473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
42350e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
42366c4ed002SBarry 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);
423739e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
423839e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
423939e2fb2aSStefano Zampini     }
424039e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
4241984c4197SStefano Zampini 
4242a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
42439162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
42449162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
42454641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
4246984c4197SStefano Zampini         /* get constraint info */
42479162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
4248984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
4249984c4197SStefano Zampini 
4250984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
42519162d606SStefano 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);
4252674ae819SStefano Zampini         }
4253984c4197SStefano Zampini 
4254fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
4255a717540cSStefano Zampini 
4256a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
4257a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
42589162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4259a717540cSStefano Zampini           }
4260984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
42619162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4262984c4197SStefano Zampini 
4263984c4197SStefano Zampini           /* compute QR decomposition of constraints */
42643f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42653f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42663f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4267674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42683f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
4269984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
4270674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4271984c4197SStefano Zampini 
4272984c4197SStefano Zampini           /* explictly compute R^-T */
4273984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
4274984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
42753f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42763f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
42773f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
42783f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
4279984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42803f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
4281984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
4282984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4283984c4197SStefano Zampini 
4284a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
42853f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42863f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
42873f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
42883f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4289984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42903f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
4291984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
4292984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4293984c4197SStefano Zampini 
4294984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
4295984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
4296984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
42973f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42983f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42993f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
43003f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43013f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
43023f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4303984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43049162d606SStefano 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));
4305984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
43069162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4307984c4197SStefano Zampini 
4308984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
43099162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
4310984c4197SStefano Zampini           /* insert cols for primal dofs */
4311984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
4312984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
43139162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4314906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4315984c4197SStefano Zampini           }
4316984c4197SStefano Zampini           /* insert cols for dual dofs */
4317984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
43189162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
4319984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
43209162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4321906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4322984c4197SStefano Zampini               j++;
4323674ae819SStefano Zampini             }
4324674ae819SStefano Zampini           }
4325984c4197SStefano Zampini 
4326984c4197SStefano Zampini           /* check change of basis */
4327984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
4328984c4197SStefano Zampini             PetscInt   ii,jj;
4329984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
4330c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
4331c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4332c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
4333c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4334c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
4335c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
4336984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4337cf5a6209SStefano 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));
4338984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4339984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
4340984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
4341cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
4342cf5a6209SStefano 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;
4343674ae819SStefano Zampini               }
4344674ae819SStefano Zampini             }
4345984c4197SStefano Zampini             if (!valid_qr) {
434622d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
4347984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
4348984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
4349cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
4350cf5a6209SStefano 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]));
4351674ae819SStefano Zampini                   }
4352cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
4353cf5a6209SStefano 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]));
4354984c4197SStefano Zampini                   }
4355984c4197SStefano Zampini                 }
4356984c4197SStefano Zampini               }
4357674ae819SStefano Zampini             } else {
435822d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
4359674ae819SStefano Zampini             }
4360674ae819SStefano Zampini           }
4361a717540cSStefano Zampini         } else { /* simple transformation block */
4362a717540cSStefano Zampini           PetscInt    row,col;
4363a6b551f4SStefano Zampini           PetscScalar val,norm;
4364a6b551f4SStefano Zampini 
4365a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
43669162d606SStefano 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));
4367a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
43689162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
43699162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4370bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
43719162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
4372906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
43739162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
4374a717540cSStefano Zampini             } else {
4375a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
43769162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4377a717540cSStefano Zampini                 if (row != col) {
43789162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
4379a717540cSStefano Zampini                 } else {
43809162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
4381a717540cSStefano Zampini                 }
4382906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
4383a717540cSStefano Zampini               }
4384a717540cSStefano Zampini             }
4385a717540cSStefano Zampini           }
438698a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
438722d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4388a717540cSStefano Zampini           }
4389674ae819SStefano Zampini         }
4390984c4197SStefano Zampini       } else {
4391984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
43929162d606SStefano 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);
4393674ae819SStefano Zampini         }
4394674ae819SStefano Zampini       }
4395674ae819SStefano Zampini     }
4396a717540cSStefano Zampini 
4397a717540cSStefano Zampini     /* free workspace */
4398a717540cSStefano Zampini     if (qr_needed) {
4399984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4400cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4401984c4197SStefano Zampini       }
4402984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4403984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4404984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4405984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4406984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4407674ae819SStefano Zampini     }
4408a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4409906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4410906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4411906d46d4SStefano Zampini 
4412906d46d4SStefano Zampini     /* assembling of global change of variable */
441388c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
4414bbb9e6c6SStefano Zampini       Mat      tmat;
441516f15bc4SStefano Zampini       PetscInt bs;
441616f15bc4SStefano Zampini 
4417906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4418906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4419bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4420bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4421bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4422bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
442316f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
442416f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4425906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4426bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4427bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4428bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4429bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4430bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4431e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4432e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4433bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4434bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
443588c03ad3SStefano Zampini 
4436906d46d4SStefano Zampini       /* check */
4437906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
4438906d46d4SStefano Zampini         PetscReal error;
4439906d46d4SStefano Zampini         Vec       x,x_change;
4440906d46d4SStefano Zampini 
4441906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4442906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4443906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4444906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4445e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4446e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4447bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4448e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4449e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4450906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4451906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4452906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4453906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4454bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4455906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
4456906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4457906d46d4SStefano Zampini       }
4458b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
4459b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
4460b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4461bf3a8328SStefano Zampini 
4462bf3a8328SStefano Zampini         if (pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined) {
4463bf3a8328SStefano Zampini           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints");CHKERRQ(ierr);
4464bf3a8328SStefano Zampini         }
4465*b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
4466ac632422SStefano Zampini           Mat                    S_new,tmat;
4467bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
4468bbb9e6c6SStefano Zampini 
4469bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
44706816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4471bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4472bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
4473bf3a8328SStefano Zampini             IS                     is_V;
4474b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4475b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4476b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4477b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4478b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4479bf3a8328SStefano Zampini           }
4480bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4481ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4482b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4483ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4484bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4485bf3a8328SStefano Zampini             const PetscScalar *array;
4486bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
4487bf3a8328SStefano Zampini             PetscInt          i,n_V;
4488bf3a8328SStefano Zampini 
4489b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4490b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4491b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4492b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4493b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4494b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
4495b087196eSStefano Zampini               PetscScalar val;
4496b087196eSStefano Zampini               PetscInt    idx;
4497b087196eSStefano Zampini 
4498b087196eSStefano Zampini               idx = idxs_V[i];
4499b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
4500b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4501b087196eSStefano Zampini             }
4502b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4503b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4504bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4505bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4506bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4507bf3a8328SStefano Zampini           }
4508ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
4509ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4510ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
4511ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4512b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4513ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4514bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
4515b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4516bf3a8328SStefano Zampini             }
4517ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
4518ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4519ac632422SStefano Zampini           }
4520b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
452188c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4522b96c3477SStefano Zampini         }
4523c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
4524*b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
4525c9db6a07SStefano Zampini           PetscInt i;
4526c9db6a07SStefano Zampini 
4527c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
4528c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
4529c9db6a07SStefano Zampini           }
4530c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
4531c9db6a07SStefano Zampini         }
4532b96c3477SStefano Zampini       }
453316909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
453416909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
453516909a7fSStefano Zampini       } else {
4536906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
453716909a7fSStefano Zampini       }
45381dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
453927b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
454072b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
454172b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
454272b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
454372b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
454472b8c272SStefano Zampini     }
45451dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
454627b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
4547b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4548b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4549906d46d4SStefano Zampini     } else {
45501dd7afcfSStefano Zampini       Mat benign_global = NULL;
455127b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
45521dd7afcfSStefano Zampini         Mat tmat;
45531dd7afcfSStefano Zampini 
45541dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
45551dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
45561dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
45571dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
45581dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
45591dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
45601dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
45611dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
45621dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
45631dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
45641dd7afcfSStefano Zampini           Mat M;
45651dd7afcfSStefano Zampini 
45661dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
45671dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
45681dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
45691dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
4570906d46d4SStefano Zampini         } else {
45711dd7afcfSStefano Zampini           Mat         eye;
45721dd7afcfSStefano Zampini           PetscScalar *array;
45731dd7afcfSStefano Zampini 
45741dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
45751dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
45761dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
45771dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
4578906d46d4SStefano Zampini           }
45791dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
45801dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45811dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45821dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
45831dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
45841dd7afcfSStefano Zampini         }
45851dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
45861dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
45871dd7afcfSStefano Zampini       }
45881dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
45891dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
45901dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
459127b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
45921dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
45931dd7afcfSStefano Zampini       }
45941dd7afcfSStefano Zampini     }
459516909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
459616909a7fSStefano Zampini       IS             is_global;
459716909a7fSStefano Zampini       const PetscInt *gidxs;
459816909a7fSStefano Zampini 
459916909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
460016909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
460116909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
460216909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
460316909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
460416909a7fSStefano Zampini     }
46051dd7afcfSStefano Zampini   }
46061dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
46071dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
4608b9b85e73SStefano Zampini   }
4609a717540cSStefano Zampini 
461072b8c272SStefano Zampini   if (!pcbddc->fake_change) {
46114f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
46124f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
46134f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
46144f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4615019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4616019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
4617019a44ceSStefano Zampini       pcbddc->local_primal_size++;
4618019a44ceSStefano Zampini     }
4619019a44ceSStefano Zampini 
4620019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
4621727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
4622727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
46239f47a83aSStefano 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);
4624c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
46250e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
46269f47a83aSStefano 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);
4627727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4628727cdba6SStefano Zampini       }
46290e6343abSStefano Zampini     }
4630727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4631b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
463272b8c272SStefano Zampini   }
463372b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4634727cdba6SStefano Zampini 
4635a717540cSStefano Zampini   /* flush dbg viewer */
4636b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4637b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4638b8ffe317SStefano Zampini   }
4639a717540cSStefano Zampini 
4640e310c8b4SStefano Zampini   /* free workspace */
4641a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
46424641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
464308122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
46449162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
46459162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
464608122e43SStefano Zampini   } else {
46479162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
46489162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
46499162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
465008122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
465108122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
46529162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
46539162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
465408122e43SStefano Zampini   }
4655674ae819SStefano Zampini   PetscFunctionReturn(0);
4656674ae819SStefano Zampini }
4657674ae819SStefano Zampini 
4658674ae819SStefano Zampini #undef __FUNCT__
4659674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4660674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4661674ae819SStefano Zampini {
4662674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4663674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4664674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
466514f95afaSStefano Zampini   PetscInt    ierr,i,N;
4666674ae819SStefano Zampini 
4667674ae819SStefano Zampini   PetscFunctionBegin;
46688e61c736SStefano Zampini   /* Reset previously computed graph */
46698e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4670674ae819SStefano Zampini   /* Init local Graph struct */
46717fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
46723bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4673674ae819SStefano Zampini 
4674575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
46755099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
46765099eff2SStefano 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);
4677575ad6abSStefano Zampini   }
46789577ea80SStefano Zampini 
4679674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4680d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
46814d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
46824d379d7bSStefano Zampini     PetscInt  nvtxs;
4683e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4684674ae819SStefano Zampini 
46852fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
46862fffb893SStefano Zampini     if (flg_row) {
46874d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4688b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
46892fffb893SStefano Zampini     }
46902fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4691674ae819SStefano Zampini   }
46929b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
46939b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4694674ae819SStefano Zampini   }
4695674ae819SStefano Zampini 
4696674ae819SStefano Zampini   /* Setup of Graph */
469714f95afaSStefano 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);
4698674ae819SStefano Zampini 
46994f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
47004f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
47014f1b2e48SStefano Zampini     PetscInt *local_subs;
47024f1b2e48SStefano Zampini 
47034f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
47044f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
47054f1b2e48SStefano Zampini       const PetscInt *idxs;
47064f1b2e48SStefano Zampini       PetscInt       nl,j;
47074f1b2e48SStefano Zampini 
47084f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
47094f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
47104f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
47114f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
47124f1b2e48SStefano Zampini       }
47134f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
47144f1b2e48SStefano Zampini     }
47154f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
47164f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
47174f1b2e48SStefano Zampini   }
47184f1b2e48SStefano Zampini 
4719674ae819SStefano Zampini   /* Graph's connected components analysis */
4720674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4721674ae819SStefano Zampini   PetscFunctionReturn(0);
4722674ae819SStefano Zampini }
4723674ae819SStefano Zampini 
4724dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4725674ae819SStefano Zampini #undef __FUNCT__
4726674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4727dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4728674ae819SStefano Zampini {
4729dc456d91SStefano Zampini   PetscSF        sf;
4730dc456d91SStefano Zampini   PetscLayout    map;
4731dc456d91SStefano Zampini   const PetscInt *idxs;
4732dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4733dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4734dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4735dc456d91SStefano Zampini   PetscMPIInt    commsize;
4736674ae819SStefano Zampini   PetscBool      first_found;
4737674ae819SStefano Zampini   PetscErrorCode ierr;
4738674ae819SStefano Zampini 
4739674ae819SStefano Zampini   PetscFunctionBegin;
4740dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4741dc456d91SStefano Zampini   if (subset_mult) {
4742dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4743dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4744dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4745674ae819SStefano Zampini   }
4746dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4747dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4748dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4749dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4750dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4751dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4752674ae819SStefano Zampini   }
4753dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4754b2566f29SBarry Smith   ierr = MPIU_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4755dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4756dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4757dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4758dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4759dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4760dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4761dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4762dc456d91SStefano Zampini 
4763dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4764dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4765dc456d91SStefano Zampini   if (subset_mult) {
4766dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4767dc456d91SStefano Zampini 
4768dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4769dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4770dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4771674ae819SStefano Zampini   } else {
4772dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4773674ae819SStefano Zampini   }
4774dc456d91SStefano Zampini   /* local size of new subset */
4775dc456d91SStefano Zampini   n_n = 0;
4776dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4777dc456d91SStefano Zampini 
4778dc456d91SStefano Zampini   /* global indexes in layout */
4779dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4780dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4781dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4782dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4783dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4784dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4785dc456d91SStefano Zampini 
4786dc456d91SStefano Zampini   /* reduce from leaves to roots */
4787dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
478864a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
478964a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4790dc456d91SStefano Zampini 
4791dc456d91SStefano Zampini   /* count indexes in local part of layout */
4792674ae819SStefano Zampini   nlocals = 0;
4793674ae819SStefano Zampini   first_index = -1;
4794674ae819SStefano Zampini   first_found = PETSC_FALSE;
4795dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4796dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4797674ae819SStefano Zampini       first_found = PETSC_TRUE;
4798674ae819SStefano Zampini       first_index = i;
4799674ae819SStefano Zampini     }
4800dc456d91SStefano Zampini     nlocals += root_data[i];
4801674ae819SStefano Zampini   }
4802dc456d91SStefano Zampini 
4803dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
48045fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4805dc456d91SStefano Zampini   start = 0;
480664a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
48075fa240b1SStefano Zampini #else
480864a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
48095fa240b1SStefano Zampini   start = start-nlocals;
48105fa240b1SStefano Zampini #endif
48115fa240b1SStefano Zampini 
4812dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4813dc456d91SStefano Zampini     *N_n = start + nlocals;
4814dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4815dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4816674ae819SStefano Zampini   }
48175fa240b1SStefano Zampini 
48185fa240b1SStefano Zampini   /* adapt root data with cumulative */
4819674ae819SStefano Zampini   if (first_found) {
4820dc456d91SStefano Zampini     PetscInt old_index;
4821dc456d91SStefano Zampini 
4822dc456d91SStefano Zampini     root_data[first_index] += start;
4823674ae819SStefano Zampini     old_index = first_index;
4824dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4825dc456d91SStefano Zampini       if (root_data[i]) {
4826dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4827674ae819SStefano Zampini         old_index = i;
4828674ae819SStefano Zampini       }
4829674ae819SStefano Zampini     }
4830674ae819SStefano Zampini   }
4831dc456d91SStefano Zampini 
4832dc456d91SStefano Zampini   /* from roots to leaves */
4833dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4834dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4835dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4836dc456d91SStefano Zampini 
4837dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4838dc456d91SStefano Zampini   if (subset_mult) {
4839dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4840dc456d91SStefano Zampini     PetscInt        cum;
4841dc456d91SStefano Zampini 
4842dc456d91SStefano Zampini     cum = 0;
4843dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4844dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4845dc456d91SStefano Zampini       PetscInt j;
4846dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4847674ae819SStefano Zampini     }
4848dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4849674ae819SStefano Zampini   } else {
4850dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4851dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4852674ae819SStefano Zampini     }
4853674ae819SStefano Zampini   }
4854dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4855dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4856674ae819SStefano Zampini   PetscFunctionReturn(0);
4857674ae819SStefano Zampini }
48589a7d3425SStefano Zampini 
48599a7d3425SStefano Zampini #undef __FUNCT__
48609a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
48619a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
48629a7d3425SStefano Zampini {
48639a7d3425SStefano Zampini   PetscInt       i,j;
48649a7d3425SStefano Zampini   PetscScalar    *alphas;
48659a7d3425SStefano Zampini   PetscErrorCode ierr;
48669a7d3425SStefano Zampini 
48679a7d3425SStefano Zampini   PetscFunctionBegin;
48689a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4869785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
48709a7d3425SStefano Zampini   for (i=0;i<n;i++) {
48719a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
48729a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
48739a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
48749a7d3425SStefano Zampini   }
48759a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
48769a7d3425SStefano Zampini   PetscFunctionReturn(0);
48779a7d3425SStefano Zampini }
48789a7d3425SStefano Zampini 
4879e7931f94SStefano Zampini #undef __FUNCT__
488070cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
488157de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
4882e7931f94SStefano Zampini {
488357de7509SStefano Zampini   Mat            A;
4884e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4885e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
488652e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
488752e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
488827b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
488957de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
489027b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
489127b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
489227b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
489327b6a85dSStefano Zampini   MPI_Comm       subcomm;
489452e5ac9dSStefano Zampini   PetscErrorCode ierr;
4895a57a6d2fSStefano Zampini 
4896e7931f94SStefano Zampini   PetscFunctionBegin;
489757de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
489857de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
489957de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
490057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
490157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
490257de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
490357de7509SStefano Zampini 
490457de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
490557de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
490657de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
490757de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
490857de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
490957de7509SStefano Zampini   im_active = !!(n);
491057de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
491157de7509SStefano Zampini   void_procs = size - active_procs;
491257de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
491357de7509SStefano Zampini   if (void_procs) {
491457de7509SStefano Zampini     PetscInt ncand;
491557de7509SStefano Zampini 
491657de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
491757de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
491857de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
491957de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
492057de7509SStefano Zampini       if (!procs_candidates[i]) {
492157de7509SStefano Zampini         procs_candidates[ncand++] = i;
492257de7509SStefano Zampini       }
492357de7509SStefano Zampini     }
492457de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
492557de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
492657de7509SStefano Zampini   }
492757de7509SStefano Zampini 
492857de7509SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix */
492957de7509SStefano Zampini   if (active_procs < *n_subdomains) {
493057de7509SStefano Zampini     PetscInt issize,isidx;
493157de7509SStefano Zampini     if (im_active) {
493257de7509SStefano Zampini       issize = 1;
493357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
493457de7509SStefano Zampini         isidx = procs_candidates[rank];
493557de7509SStefano Zampini       } else {
493657de7509SStefano Zampini         isidx = rank;
493757de7509SStefano Zampini       }
493857de7509SStefano Zampini     } else {
493957de7509SStefano Zampini       issize = 0;
494057de7509SStefano Zampini       isidx = -1;
494157de7509SStefano Zampini     }
494257de7509SStefano Zampini     *n_subdomains = active_procs;
494357de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
4944daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
494557de7509SStefano Zampini     PetscFunctionReturn(0);
494657de7509SStefano Zampini   }
4947c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
4948c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
494927b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
4950e7931f94SStefano Zampini 
4951e7931f94SStefano Zampini   /* Get info on mapping */
49523bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
49533bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4954e7931f94SStefano Zampini 
4955e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4956785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4957e7931f94SStefano Zampini   xadj[0] = 0;
4958e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4959785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4960785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
496127b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
496227b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
496327b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
496427b6a85dSStefano Zampini       count[shared[i][j]] += 1;
4965e7931f94SStefano Zampini 
496627b6a85dSStefano Zampini   xadj_count = 0;
49672b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
496827b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
496927b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
4970d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4971d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4972d023bfaeSStefano Zampini         xadj_count++;
497327b6a85dSStefano Zampini         break;
497427b6a85dSStefano Zampini       }
4975e7931f94SStefano Zampini     }
4976e7931f94SStefano Zampini   }
4977d023bfaeSStefano Zampini   xadj[1] = xadj_count;
497827b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
49793bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4980e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4981e7931f94SStefano Zampini 
49823837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4983e7931f94SStefano Zampini 
498427b6a85dSStefano Zampini   /* Restrict work on active processes only */
498527b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
498627b6a85dSStefano Zampini   if (void_procs) {
498727b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
498827b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
498927b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
499027b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
499127b6a85dSStefano Zampini   } else {
499227b6a85dSStefano Zampini     psubcomm = NULL;
499327b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
499427b6a85dSStefano Zampini   }
499527b6a85dSStefano Zampini 
499627b6a85dSStefano Zampini   v_wgt = NULL;
499727b6a85dSStefano Zampini   if (!color) {
4998e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4999e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
5000e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5001c8587f34SStefano Zampini   } else {
500252e5ac9dSStefano Zampini     Mat             subdomain_adj;
500352e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
500452e5ac9dSStefano Zampini     MatPartitioning partitioner;
500527b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
500652e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
500757de7509SStefano Zampini     PetscMPIInt     size;
5008b0c7d250SStefano Zampini     PetscBool       aggregate;
5009b0c7d250SStefano Zampini 
501027b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
501127b6a85dSStefano Zampini     if (void_procs) {
501227b6a85dSStefano Zampini       PetscInt prank = rank;
5013785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
501427b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
5015e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
5016e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
5017c8587f34SStefano Zampini       }
5018e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
501927b6a85dSStefano Zampini     } else {
502027b6a85dSStefano Zampini       oldranks = NULL;
502127b6a85dSStefano Zampini     }
5022b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
502327b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
5024b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
5025b0c7d250SStefano Zampini       PetscMPIInt nrank;
5026b0c7d250SStefano Zampini       PetscScalar *vals;
5027b0c7d250SStefano Zampini 
502827b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
5029b0c7d250SStefano Zampini       lrows = 0;
5030b0c7d250SStefano Zampini       if (nrank<redprocs) {
5031b0c7d250SStefano Zampini         lrows = size/redprocs;
5032b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
5033b0c7d250SStefano Zampini       }
503427b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
5035b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
5036b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5037b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5038b0c7d250SStefano Zampini       row = nrank;
5039b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
5040b0c7d250SStefano Zampini       cols = adjncy;
5041b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
5042b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5043b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5044b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5045b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
504652e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
504752e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
504852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5049b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
505027b6a85dSStefano Zampini       if (use_vwgt) {
505127b6a85dSStefano Zampini         Vec               v;
505227b6a85dSStefano Zampini         const PetscScalar *array;
505327b6a85dSStefano Zampini         PetscInt          nl;
505427b6a85dSStefano Zampini 
505527b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
505627b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
505727b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
505827b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
505927b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
506027b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
506127b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
506222db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
506327b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
506427b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
506527b6a85dSStefano Zampini       }
5066b0c7d250SStefano Zampini     } else {
506727b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
506827b6a85dSStefano Zampini       if (use_vwgt) {
506927b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
507027b6a85dSStefano Zampini         v_wgt[0] = local_size;
507127b6a85dSStefano Zampini       }
5072b0c7d250SStefano Zampini     }
507322b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5074e7931f94SStefano Zampini 
5075e7931f94SStefano Zampini     /* Partition */
507627b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5077e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
507827b6a85dSStefano Zampini     if (v_wgt) {
5079e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5080c8587f34SStefano Zampini     }
508157de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
508257de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5083e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5084e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
508522b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5086e7931f94SStefano Zampini 
508752e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
508852e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
508952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
509052e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
509157de7509SStefano Zampini     if (!aggregate) {
509257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
509327b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
509427b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
509527b6a85dSStefano Zampini #endif
509657de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
509727b6a85dSStefano Zampini       } else if (oldranks) {
5098b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
509927b6a85dSStefano Zampini       } else {
510027b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
510157de7509SStefano Zampini       }
510228143c3dSStefano Zampini     } else {
5103b0c7d250SStefano Zampini       PetscInt    idxs[1];
5104b0c7d250SStefano Zampini       PetscMPIInt tag;
5105b0c7d250SStefano Zampini       MPI_Request *reqs;
5106b0c7d250SStefano Zampini 
5107b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5108b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5109b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
511027b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
511128143c3dSStefano Zampini       }
511227b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5113b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5114b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
511557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
511627b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
511727b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
511827b6a85dSStefano Zampini #endif
511957de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
512027b6a85dSStefano Zampini       } else if (oldranks) {
5121b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
512227b6a85dSStefano Zampini       } else {
512327b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5124e7931f94SStefano Zampini       }
512557de7509SStefano Zampini     }
512652e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5127e7931f94SStefano Zampini     /* clean up */
5128e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
512952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5130e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5131e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5132e7931f94SStefano Zampini   }
513327b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
513457de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5135e7931f94SStefano Zampini 
5136e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5137e7931f94SStefano Zampini   i = 1;
513827b6a85dSStefano Zampini   if (!color) i=0;
513957de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5140e7931f94SStefano Zampini   PetscFunctionReturn(0);
5141e7931f94SStefano Zampini }
5142e7931f94SStefano Zampini 
5143e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5144e7931f94SStefano Zampini 
5145e7931f94SStefano Zampini #undef __FUNCT__
5146e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
514757de7509SStefano 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[])
5148e7931f94SStefano Zampini {
514970cf5478SStefano Zampini   Mat                    local_mat;
5150e7931f94SStefano Zampini   IS                     is_sends_internal;
51519d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
515228143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
51539d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
5154e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
5155e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
5156e7931f94SStefano Zampini   const PetscInt*        is_indices;
5157e7931f94SStefano Zampini   MatType                new_local_type;
5158e7931f94SStefano Zampini   /* buffers */
5159e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
516028143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
51619d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
5162e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
5163e7931f94SStefano Zampini   /* MPI */
516428143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
516528143c3dSStefano Zampini   PetscSubcomm           subcomm;
5166e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
516728143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
516828143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
516928143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
517028143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
517128143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
5172e7931f94SStefano Zampini   PetscErrorCode         ierr;
5173e7931f94SStefano Zampini 
5174e7931f94SStefano Zampini   PetscFunctionBegin;
517557de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5176e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
517728143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
517857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
517957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
518057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
518157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
518257de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
518357de7509SStefano Zampini 
518457de7509SStefano Zampini   /* further checks */
5185e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5186e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5187e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
5188e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
5189e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
519057de7509SStefano Zampini   if (reuse && *mat_n) {
519170cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
519257de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
519370cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
519428143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
519570cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
519670cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
519770cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
519870cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
519970cf5478SStefano Zampini   }
5200e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
5201e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
520257de7509SStefano Zampini 
5203e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
5204e7931f94SStefano Zampini   if (!is_sends) {
520528143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
520657de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
5207c8587f34SStefano Zampini   } else {
5208e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
5209e7931f94SStefano Zampini     is_sends_internal = is_sends;
5210c8587f34SStefano Zampini   }
5211e7931f94SStefano Zampini 
5212e7931f94SStefano Zampini   /* get comm */
5213a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
5214e7931f94SStefano Zampini 
5215e7931f94SStefano Zampini   /* compute number of sends */
5216e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
5217e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
5218e7931f94SStefano Zampini 
5219e7931f94SStefano Zampini   /* compute number of receives */
5220e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
5221785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
5222e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
5223e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5224e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
5225e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
5226e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
5227e7931f94SStefano Zampini 
522828143c3dSStefano Zampini   /* restrict comm if requested */
522928143c3dSStefano Zampini   subcomm = 0;
523028143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
523128143c3dSStefano Zampini   if (restrict_comm) {
5232779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
5233779c1cceSStefano Zampini 
523428143c3dSStefano Zampini     color = 0;
523553a05cb3SStefano Zampini     if (restrict_full) {
523653a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
523753a05cb3SStefano Zampini     } else {
523853a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
523953a05cb3SStefano Zampini     }
5240b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
524128143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
524228143c3dSStefano Zampini     /* check if reuse has been requested */
524357de7509SStefano Zampini     if (reuse) {
524428143c3dSStefano Zampini       if (*mat_n) {
524528143c3dSStefano Zampini         PetscMPIInt subcommsize2;
524628143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
524728143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
524828143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
524928143c3dSStefano Zampini       } else {
525028143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
525128143c3dSStefano Zampini       }
525228143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
5253779c1cceSStefano Zampini       PetscMPIInt rank;
5254779c1cceSStefano Zampini 
5255779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
525628143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
525728143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
525828143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
5259306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
526028143c3dSStefano Zampini     }
526128143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
526228143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
526328143c3dSStefano Zampini   } else {
526428143c3dSStefano Zampini     comm_n = comm;
526528143c3dSStefano Zampini   }
526628143c3dSStefano Zampini 
5267e7931f94SStefano Zampini   /* prepare send/receive buffers */
5268785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
5269e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
5270785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
5271e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
527228143c3dSStefano Zampini   if (nis) {
5273854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
527428143c3dSStefano Zampini   }
5275e7931f94SStefano Zampini 
527628143c3dSStefano Zampini   /* Get data from local matrices */
52776c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
5278e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
5279e7931f94SStefano Zampini     /*
5280e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
5281e7931f94SStefano Zampini        send_buffer_idxs should contain:
5282e7931f94SStefano Zampini        - MatType_PRIVATE type
5283e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
5284e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
5285e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
5286e7931f94SStefano Zampini     */
52876c4ed002SBarry Smith   else {
5288e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
52893bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
5290854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
5291e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
5292e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
52933bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5294e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
52953bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5296e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
5297e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
5298e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
5299e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
5300c8587f34SStefano Zampini     }
5301c8587f34SStefano Zampini   }
5302e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
530328143c3dSStefano Zampini   /* additional is (if any) */
530428143c3dSStefano Zampini   if (nis) {
530528143c3dSStefano Zampini     PetscMPIInt psum;
530628143c3dSStefano Zampini     PetscInt j;
530728143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
530828143c3dSStefano Zampini       PetscInt plen;
530928143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
531028143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
531128143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
531228143c3dSStefano Zampini     }
5313854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
531428143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
531528143c3dSStefano Zampini       PetscInt plen;
531628143c3dSStefano Zampini       const PetscInt *is_array_idxs;
531728143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
531828143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
531928143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
532028143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
532128143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
532228143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
532328143c3dSStefano Zampini     }
532428143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
532528143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
532628143c3dSStefano Zampini     }
532728143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
532828143c3dSStefano Zampini   }
532928143c3dSStefano Zampini 
5330e7931f94SStefano Zampini   buf_size_idxs = 0;
5331e7931f94SStefano Zampini   buf_size_vals = 0;
533228143c3dSStefano Zampini   buf_size_idxs_is = 0;
5333e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5334e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
5335e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
533628143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
5337e7931f94SStefano Zampini   }
5338785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
5339785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
534095ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
5341e7931f94SStefano Zampini 
5342e7931f94SStefano Zampini   /* get new tags for clean communications */
5343e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
5344e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
534528143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
5346e7931f94SStefano Zampini 
5347e7931f94SStefano Zampini   /* allocate for requests */
5348785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
5349785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
535095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
5351785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
5352785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
535395ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
5354e7931f94SStefano Zampini 
5355e7931f94SStefano Zampini   /* communications */
5356e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
5357e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
535828143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
5359e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5360e7931f94SStefano Zampini     source_dest = onodes[i];
5361e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
5362e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
5363e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5364e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
536528143c3dSStefano Zampini     if (nis) {
536657de7509SStefano Zampini       source_dest = onodes_is[i];
536728143c3dSStefano 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);
536828143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
536928143c3dSStefano Zampini     }
5370e7931f94SStefano Zampini   }
5371e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
5372e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
5373e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
5374e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
537528143c3dSStefano Zampini     if (nis) {
537628143c3dSStefano 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);
537728143c3dSStefano Zampini     }
5378e7931f94SStefano Zampini   }
5379e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5380e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
5381e7931f94SStefano Zampini 
5382e7931f94SStefano Zampini   /* assemble new l2g map */
5383e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5384e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
53859d30be91SStefano Zampini   new_local_rows = 0;
5386e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
53879d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5388e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5389e7931f94SStefano Zampini   }
53909d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
5391e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
53929d30be91SStefano Zampini   new_local_rows = 0;
5393e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
53949d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
53959d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5396e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5397e7931f94SStefano Zampini   }
53989d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
53999d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
5400e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
5401e7931f94SStefano Zampini 
5402e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
5403e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
5404e7931f94SStefano 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) */
5405e7931f94SStefano Zampini   if (n_recvs) {
540628143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
5407e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
5408e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
5409e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
5410e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
5411e7931f94SStefano Zampini         break;
5412e7931f94SStefano Zampini       }
5413e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
5414e7931f94SStefano Zampini     }
5415e7931f94SStefano Zampini     switch (new_local_type_private) {
541628143c3dSStefano Zampini       case MATDENSE_PRIVATE:
541728143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
5418e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
5419e7931f94SStefano Zampini           bs = 1;
542028143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
542128143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
542228143c3dSStefano Zampini           bs = 1;
542328143c3dSStefano Zampini         }
5424e7931f94SStefano Zampini         break;
5425e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
5426e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
5427e7931f94SStefano Zampini         bs = 1;
5428e7931f94SStefano Zampini         break;
5429e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
5430e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
5431e7931f94SStefano Zampini         break;
5432e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
5433e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
5434e7931f94SStefano Zampini         break;
5435e7931f94SStefano Zampini       default:
54369d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
5437e7931f94SStefano Zampini         break;
5438e7931f94SStefano Zampini     }
543928143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
544028143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
544128143c3dSStefano Zampini     bs = 1;
5442e7931f94SStefano Zampini   }
5443e7931f94SStefano Zampini 
544470cf5478SStefano Zampini   /* create MATIS object if needed */
544557de7509SStefano Zampini   if (!reuse) {
5446e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
5447e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
544870cf5478SStefano Zampini   } else {
544970cf5478SStefano Zampini     /* it also destroys the local matrices */
545057de7509SStefano Zampini     if (*mat_n) {
545170cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
545257de7509SStefano Zampini     } else { /* this is a fake object */
545357de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
545457de7509SStefano Zampini     }
545570cf5478SStefano Zampini   }
545670cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
5457e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
54589d30be91SStefano Zampini 
54599d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
54609d30be91SStefano Zampini 
54619d30be91SStefano Zampini   /* Global to local map of received indices */
54629d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
54639d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
54649d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
54659d30be91SStefano Zampini 
54669d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
54679d30be91SStefano Zampini   buf_size_idxs = 0;
54689d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
54699d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
54709d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
54719d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
54729d30be91SStefano Zampini   }
54739d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
54749d30be91SStefano Zampini 
54759d30be91SStefano Zampini   /* set preallocation */
54769d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
54779d30be91SStefano Zampini   if (!newisdense) {
54789d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
54799d30be91SStefano Zampini 
54809d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
54819d30be91SStefano Zampini     if (n_recvs) {
54829d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
54839d30be91SStefano Zampini     }
54849d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
54859d30be91SStefano Zampini       PetscInt j;
54869d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
54879d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
54889d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
54899d30be91SStefano Zampini         }
54909d30be91SStefano Zampini       } else {
54919d30be91SStefano Zampini         /* TODO */
54929d30be91SStefano Zampini       }
54939d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
54949d30be91SStefano Zampini     }
54959d30be91SStefano Zampini     if (new_local_nnz) {
54969d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
54979d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
54989d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
54999d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
55009d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
55019d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
55029d30be91SStefano Zampini     } else {
55039d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
55049d30be91SStefano Zampini     }
55059d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
55069d30be91SStefano Zampini   } else {
55079d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
55089d30be91SStefano Zampini   }
5509e7931f94SStefano Zampini 
5510e7931f94SStefano Zampini   /* set values */
5511e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
55129d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5513e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5514e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5515e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
55169d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5517e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5518e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5519e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
552028143c3dSStefano Zampini     } else {
552128143c3dSStefano Zampini       /* TODO */
5522e7931f94SStefano Zampini     }
5523e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5524e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5525e7931f94SStefano Zampini   }
5526e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5527e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
552870cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
552970cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55309d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
55319d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5532e7931f94SStefano Zampini 
5533dfd14d43SStefano Zampini #if 0
553428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5535e7931f94SStefano Zampini     Vec       lvec,rvec;
5536e7931f94SStefano Zampini     PetscReal infty_error;
5537e7931f94SStefano Zampini 
55382a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5539e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5540e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5541e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
554270cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5543e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5544e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5545e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5546e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5547e7931f94SStefano Zampini   }
554828143c3dSStefano Zampini #endif
5549e7931f94SStefano Zampini 
555028143c3dSStefano Zampini   /* assemble new additional is (if any) */
555128143c3dSStefano Zampini   if (nis) {
555228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
555328143c3dSStefano Zampini 
555428143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5555854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
555628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
555728143c3dSStefano Zampini     psum = 0;
555828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
555928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
556028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
556128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
556228143c3dSStefano Zampini         psum += plen;
556328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
556428143c3dSStefano Zampini       }
556528143c3dSStefano Zampini     }
5566854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5567854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
556828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
556928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
557028143c3dSStefano Zampini     }
557128143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
557228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
557328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
557428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
557528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
557628143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
557728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
557828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
557928143c3dSStefano Zampini       }
558028143c3dSStefano Zampini     }
558128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
558228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
558328143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
558428143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
558528143c3dSStefano Zampini     }
558628143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
558728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
558828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
558928143c3dSStefano Zampini   }
5590e7931f94SStefano Zampini   /* free workspace */
559128143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5592e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5593e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5594e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5595e7931f94SStefano Zampini   if (isdense) {
5596e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5597e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5598e7931f94SStefano Zampini   } else {
5599e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5600e7931f94SStefano Zampini   }
560128143c3dSStefano Zampini   if (nis) {
560228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
560328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
560428143c3dSStefano Zampini   }
5605e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5606e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
560728143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5608e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5609e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
561028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5611e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5612e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5613e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5614e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5615e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
561628143c3dSStefano Zampini   if (nis) {
561728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
561828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
561928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
562028143c3dSStefano Zampini   }
562128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
562228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
562328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
562428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
562528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
562628143c3dSStefano Zampini     }
562753a05cb3SStefano Zampini     *mat_n = NULL;
562828143c3dSStefano Zampini   }
5629e7931f94SStefano Zampini   PetscFunctionReturn(0);
5630e7931f94SStefano Zampini }
5631a57a6d2fSStefano Zampini 
563212edc857SStefano Zampini /* temporary hack into ksp private data structure */
5633af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
563412edc857SStefano Zampini 
5635c8587f34SStefano Zampini #undef __FUNCT__
5636c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5637c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5638c8587f34SStefano Zampini {
5639c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5640c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
564120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
56429881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
564320a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
56446e683305SStefano Zampini   IS                     coarse_is,*isarray;
56456e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
564630368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5647f9eb5b7dSStefano Zampini   PC                     pc_temp;
5648c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5649c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5650f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
56514f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
56526e683305SStefano Zampini   Mat                    t_coarse_mat_is;
565357de7509SStefano Zampini   PetscInt               ncoarse;
565468457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
565522bc73bbSStefano Zampini   PetscScalar            *array;
565657de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
565757de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
56589881197aSStefano Zampini   PetscErrorCode         ierr;
5659fdc09c96SStefano Zampini 
5660c8587f34SStefano Zampini   PetscFunctionBegin;
5661c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
566268457ee5SStefano 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 */
5663fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
56645a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5665fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5666f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5667f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5668f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5669fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
567051bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
567151bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5672dc4bcba2SStefano Zampini         PC        pc;
5673dc4bcba2SStefano Zampini         PetscBool isbddc;
5674dc4bcba2SStefano Zampini 
5675dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5676dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5677dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5678dc4bcba2SStefano Zampini         if (isbddc) {
567963c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
568063c961adSStefano Zampini         } else {
5681727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
568263c961adSStefano Zampini         }
5683fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5684fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5685fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5686f4ddd8eeSStefano Zampini       }
5687fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5688fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5689f4ddd8eeSStefano Zampini     }
569070cf5478SStefano Zampini     /* reset any subassembling information */
569157de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
569270cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
569357de7509SStefano Zampini     }
56946e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5695fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5696f4ddd8eeSStefano Zampini   }
569757de7509SStefano Zampini   /* assemble coarse matrix */
569857de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
569957de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
570057de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
570157de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
570218a45a71SStefano Zampini   } else {
570357de7509SStefano Zampini     coarse_mat = NULL;
570457de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
57056e683305SStefano Zampini   }
5706e7931f94SStefano Zampini 
5707abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5708abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5709abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5710abbbba34SStefano Zampini 
5711abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
571222bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
571322bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
571422bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
571522bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5716e176bc59SStefano 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);
57176e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
57186e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57196e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5720abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5721abbbba34SStefano Zampini 
572257de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
572357de7509SStefano Zampini   im_active = !!(pcis->n);
572457de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
572557de7509SStefano Zampini 
572657de7509SStefano Zampini   /* determine number of process partecipating to coarse solver and compute subassembling pattern */
572757de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
572857de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
572957de7509SStefano Zampini   coarse_mat_is = NULL;
573057de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
573157de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
573257de7509SStefano Zampini   full_restr = PETSC_TRUE;
573357de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(pcbddc->coarse_size,pcbddc->coarse_eqs_per_proc);
573457de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
573557de7509SStefano Zampini   if (multilevel_requested) {
573657de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
573757de7509SStefano Zampini     restr = PETSC_FALSE;
573857de7509SStefano Zampini     full_restr = PETSC_FALSE;
573957de7509SStefano Zampini   } else {
574057de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
574157de7509SStefano Zampini     restr = PETSC_TRUE;
574257de7509SStefano Zampini     full_restr = PETSC_TRUE;
574357de7509SStefano Zampini   }
574457de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
574557de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
574657de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
574757de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
574857de7509SStefano Zampini     PetscInt    psum;
574957de7509SStefano Zampini     PetscMPIInt size;
575057de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
575157de7509SStefano Zampini     else psum = 0;
575257de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
575357de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
575457de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
575557de7509SStefano Zampini   }
575657de7509SStefano Zampini   /* determine if we can go multilevel */
575757de7509SStefano Zampini   if (multilevel_requested) {
575857de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
575957de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
576057de7509SStefano Zampini   }
576157de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
576257de7509SStefano Zampini 
5763e4d548c7SStefano Zampini   /* dump subassembling pattern */
5764e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
5765e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
5766e4d548c7SStefano Zampini   }
5767e4d548c7SStefano Zampini 
57686e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
576927b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
57706e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
57716e683305SStefano Zampini     const PetscInt         *idxs;
57726e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
57736e683305SStefano Zampini 
57746e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
57750be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
57766e683305SStefano Zampini     /* allocate space for temporary storage */
5777854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5778854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
57796e683305SStefano Zampini     /* allocate for IS array */
57806e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
57816e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
578227b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
578330368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5784854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
57856e683305SStefano Zampini     /* dofs splitting */
57866e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
57876e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
57886e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
57896e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
57906e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
57916e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
57926e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
579330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
57946e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
57956e683305SStefano Zampini     }
57966e683305SStefano Zampini     /* neumann boundaries */
57976e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
57986e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
57996e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
58006e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
58016e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
58026e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&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[nisdofs]);CHKERRQ(ierr);
58056e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
58066e683305SStefano Zampini     }
58076e683305SStefano Zampini     /* free memory */
58086e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
58096e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
58106e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
58116e683305SStefano Zampini   } else {
58126e683305SStefano Zampini     nis = 0;
58136e683305SStefano Zampini     nisdofs = 0;
58146e683305SStefano Zampini     nisneu = 0;
581530368db7SStefano Zampini     nisvert = 0;
58166e683305SStefano Zampini     isarray = NULL;
58176e683305SStefano Zampini   }
58186e683305SStefano Zampini   /* destroy no longer needed map */
58196e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
58206e683305SStefano Zampini 
582157de7509SStefano Zampini   /* subassemble */
582257de7509SStefano Zampini   if (multilevel_allowed) {
582357de7509SStefano Zampini     PetscBool reuse,reuser;
582457de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
582557de7509SStefano Zampini     else reuse = PETSC_FALSE;
582657de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
582757de7509SStefano Zampini     if (reuser) {
582857de7509SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray);CHKERRQ(ierr);
582974e2c79eSStefano Zampini     } else {
583057de7509SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
583174e2c79eSStefano Zampini     }
58321f4df5f7SStefano 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 */
583374e2c79eSStefano Zampini   } else {
583457de7509SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
58356e683305SStefano Zampini   }
583657de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
583757de7509SStefano Zampini     PetscMPIInt size;
583857de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
583957de7509SStefano Zampini     if (!multilevel_allowed) {
584057de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
58416e683305SStefano Zampini     } else {
584257de7509SStefano Zampini       Mat A;
5843779c1cceSStefano Zampini 
584457de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
584557de7509SStefano Zampini       if (coarse_mat_is) {
584657de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
584757de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
584857de7509SStefano Zampini         coarse_mat = coarse_mat_is;
584957de7509SStefano Zampini       }
585057de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
585157de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
585257de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
5853779c1cceSStefano Zampini     }
5854779c1cceSStefano Zampini   }
585557de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
585657de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
58576e683305SStefano Zampini 
58586e683305SStefano Zampini   /* create local to global scatters for coarse problem */
585968457ee5SStefano Zampini   if (compute_vecs) {
58606e683305SStefano Zampini     PetscInt lrows;
58616e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
586257de7509SStefano Zampini     if (coarse_mat) {
586357de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
58646e683305SStefano Zampini     } else {
58656e683305SStefano Zampini       lrows = 0;
58666e683305SStefano Zampini     }
58676e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
58686e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
58696e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
58706e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
58716e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
58726e683305SStefano Zampini   }
58736e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
5874c8587f34SStefano Zampini 
5875f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5876f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5877f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5878f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5879f9eb5b7dSStefano Zampini   } else {
5880f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5881f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5882c8587f34SStefano Zampini   }
5883c8587f34SStefano Zampini 
58846e683305SStefano Zampini   /* print some info if requested */
58856e683305SStefano Zampini   if (pcbddc->dbg_flag) {
58866e683305SStefano Zampini     if (!multilevel_allowed) {
58876e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
58886e683305SStefano Zampini       if (multilevel_requested) {
58896e683305SStefano 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);
58906e683305SStefano Zampini       } else if (pcbddc->max_levels) {
58916e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
58926e683305SStefano Zampini       }
58936e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
58946e683305SStefano Zampini     }
58956e683305SStefano Zampini   }
58966e683305SStefano Zampini 
5897f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
589857de7509SStefano Zampini   if (coarse_mat) {
58996a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
59006e683305SStefano Zampini     if (pcbddc->dbg_flag) {
590157de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
59026e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
59036e683305SStefano Zampini     }
5904f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5905312be037SStefano Zampini       char prefix[256],str_level[16];
5906e604994aSStefano Zampini       size_t len;
590757de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5908422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5909c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5910f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
591157de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5912c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
59136e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5914c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5915c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5916e604994aSStefano Zampini       /* prefix */
5917e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5918e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5919e604994aSStefano Zampini       if (!pcbddc->current_level) {
5920e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5921e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5922c8587f34SStefano Zampini       } else {
5923e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5924312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5925312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
592634d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5927312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5928e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5929e604994aSStefano Zampini       }
5930e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
59313e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
59323e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
59333e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
59343e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5935f9eb5b7dSStefano Zampini       /* allow user customization */
5936f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
59373e3c6dadSStefano Zampini     }
59383e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
593951bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
59403e3c6dadSStefano Zampini     if (nisdofs) {
59413e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
59423e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
59433e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
59443e3c6dadSStefano Zampini       }
59453e3c6dadSStefano Zampini     }
59463e3c6dadSStefano Zampini     if (nisneu) {
59473e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
59483e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5949312be037SStefano Zampini     }
595030368db7SStefano Zampini     if (nisvert) {
595130368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
595230368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
595330368db7SStefano Zampini     }
5954f9eb5b7dSStefano Zampini 
5955f9eb5b7dSStefano Zampini     /* get some info after set from options */
5956f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5957f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
59584f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
59596e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5960f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5961f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5962f9eb5b7dSStefano Zampini     }
596339f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
59644f3a063dSStefano Zampini     if (isredundant) {
59654f3a063dSStefano Zampini       KSP inner_ksp;
59664f3a063dSStefano Zampini       PC  inner_pc;
59674f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
59684f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
59694f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
59704f3a063dSStefano Zampini     }
5971f9eb5b7dSStefano Zampini 
597257de7509SStefano Zampini     /* parameters which miss an API */
597357de7509SStefano Zampini     if (isbddc) {
5974720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
5975720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
597657de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
597727b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
597827b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
597927b6a85dSStefano Zampini         pcbddc_coarse->benign_compute_nonetflux = PETSC_TRUE;
5980720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
598159e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
5982720d30f9SStefano Zampini       }
5983d4d8cf7bSStefano Zampini     }
59849881197aSStefano Zampini 
59853301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
59865a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
59873301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
59883301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
59893301b35fSStefano Zampini     }
59903301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
59913301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
59923301b35fSStefano Zampini     }
59933301b35fSStefano Zampini     if (pc->pmat->spd_set) {
59943301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
59953301b35fSStefano Zampini     }
599627b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
599727b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
599827b6a85dSStefano Zampini     }
59996e683305SStefano Zampini     /* set operators */
60005f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
60016e683305SStefano Zampini     if (pcbddc->dbg_flag) {
60026e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
60036e683305SStefano Zampini     }
60046e683305SStefano Zampini   }
60056e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
6006b1ecc7b1SStefano Zampini #if 0
6007b9b85e73SStefano Zampini   {
6008b9b85e73SStefano Zampini     PetscViewer viewer;
6009b9b85e73SStefano Zampini     char filename[256];
6010b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
6011b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
60126a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6013b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
6014f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
6015b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
6016b9b85e73SStefano Zampini   }
6017b9b85e73SStefano Zampini #endif
6018f9eb5b7dSStefano Zampini 
601998a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
602098a51de6SStefano Zampini     Vec crhs,csol;
602104708bb6SStefano Zampini 
6022f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
6023f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
6024f347579bSStefano Zampini     if (!csol) {
60252a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
6026f9eb5b7dSStefano Zampini     }
6027f347579bSStefano Zampini     if (!crhs) {
60282a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
6029f347579bSStefano Zampini     }
6030b0f5fe93SStefano Zampini   }
6031b0f5fe93SStefano Zampini 
6032b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
6033b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
6034b0f5fe93SStefano Zampini 
6035b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
60364f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
60374f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
60384f1b2e48SStefano Zampini     }
6039b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
6040b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
6041b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6042b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6043b0f5fe93SStefano Zampini     if (coarse_mat) {
6044b0f5fe93SStefano Zampini       Vec         nullv;
6045b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
6046b0f5fe93SStefano Zampini       PetscInt    nl;
6047b0f5fe93SStefano Zampini 
6048b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
6049b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
6050b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6051b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
6052b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
6053b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
6054b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6055b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
6056b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
6057b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
6058b0f5fe93SStefano Zampini     }
6059b0f5fe93SStefano Zampini   }
6060b0f5fe93SStefano Zampini 
6061b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
6062b0f5fe93SStefano Zampini     PetscBool ispreonly;
6063b0f5fe93SStefano Zampini 
6064b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
6065b0f5fe93SStefano Zampini       PetscBool isnull;
6066b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
6067bef83e63SStefano Zampini       if (isnull) {
6068b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
6069b0f5fe93SStefano Zampini       }
6070bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
6071b0f5fe93SStefano Zampini     }
6072b0f5fe93SStefano Zampini     /* setup coarse ksp */
6073b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
6074cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
6075cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
60766e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
6077c8587f34SStefano Zampini       KSP       check_ksp;
60782b510759SStefano Zampini       KSPType   check_ksp_type;
6079c8587f34SStefano Zampini       PC        check_pc;
60806e683305SStefano Zampini       Vec       check_vec,coarse_vec;
60816a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
60822b510759SStefano Zampini       PetscInt  its;
60836e683305SStefano Zampini       PetscBool compute_eigs;
60846e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
60856e683305SStefano Zampini       PetscInt  neigs;
60868e185a42SStefano Zampini       const char *prefix;
6087c8587f34SStefano Zampini 
60882b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
60896e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
6090422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
609123ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6092f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
6093e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
6094e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
6095e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
60962b510759SStefano Zampini       if (ispreonly) {
60972b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
60986e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
60992b510759SStefano Zampini       } else {
6100cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
61016e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
6102c8587f34SStefano Zampini       }
6103c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
61046e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
61056e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
61066e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
6107a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
6108a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
6109a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
6110a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
6111c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
6112c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
6113c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
6114c8587f34SStefano Zampini       /* create random vec */
61152701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
6116c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
61176e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
6118c8587f34SStefano Zampini       /* solve coarse problem */
61196e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
6120cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
61216e683305SStefano Zampini       if (compute_eigs) {
6122854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
6123854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
61246e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
61256e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
61266e683305SStefano Zampini         lambda_min = eigs_r[0];
61276e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
61282701bc32SStefano Zampini           if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
61292701bc32SStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
6130cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
6131cbcc2c2aSStefano Zampini           }
6132c8587f34SStefano Zampini         }
6133c8587f34SStefano Zampini       }
6134cbcc2c2aSStefano Zampini 
6135c8587f34SStefano Zampini       /* check coarse problem residual error */
61366e683305SStefano Zampini       if (pcbddc->dbg_flag) {
61376e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
61386e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
61396e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
6140c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
61416e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
61426e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
6143779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
61446e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
61456e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
61466e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
61476e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
6148b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
6149b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
6150b0f5fe93SStefano Zampini         }
61516e683305SStefano Zampini         if (compute_eigs) {
61526e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
6153deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
6154c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
61556e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
61566e683305SStefano 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);
61576e683305SStefano Zampini           for (i=0;i<neigs;i++) {
61586e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
6159c8587f34SStefano Zampini           }
61606e683305SStefano Zampini         }
61616e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
61626e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
61636e683305SStefano Zampini       }
6164e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
61652701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
6166c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
61676e683305SStefano Zampini       if (compute_eigs) {
61686e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
61696e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
6170c8587f34SStefano Zampini       }
61716e683305SStefano Zampini     }
61726e683305SStefano Zampini   }
6173bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6174cbcc2c2aSStefano Zampini   /* print additional info */
6175cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
61766e683305SStefano Zampini     /* waits until all processes reaches this point */
61776e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
6178cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
6179cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6180cbcc2c2aSStefano Zampini   }
6181cbcc2c2aSStefano Zampini 
61822b510759SStefano Zampini   /* free memory */
6183fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
6184c8587f34SStefano Zampini   PetscFunctionReturn(0);
6185c8587f34SStefano Zampini }
6186674ae819SStefano Zampini 
6187f34684f1SStefano Zampini #undef __FUNCT__
6188f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
6189f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
6190f34684f1SStefano Zampini {
6191f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6192f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
6193f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
6194dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
6195dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
619673be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
6197dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
6198f34684f1SStefano Zampini   PetscErrorCode ierr;
6199f34684f1SStefano Zampini 
6200f34684f1SStefano Zampini   PetscFunctionBegin;
6201f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
62026c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
6203dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
62043bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
6205dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6206dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
6207dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
6208dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
6209dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
6210dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
62116c4ed002SBarry 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);
6212dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
6213dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6214dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
6215dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6216dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6217f34684f1SStefano Zampini 
6218f34684f1SStefano Zampini   /* check numbering */
6219f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
6220019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
6221dc456d91SStefano Zampini     PetscInt    i;
6222b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
6223f34684f1SStefano Zampini 
6224f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6225f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
6226f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
62271575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6228019a44ceSStefano Zampini     /* counter */
6229019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6230019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6231019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6232019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6233019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6234019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6235f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
6236f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
6237727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6238f34684f1SStefano Zampini     }
6239f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6240f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6241f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6242e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6243e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6244e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6245e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6246f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6247019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6248f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6249019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
62502c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
625175c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
6252b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
62532c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
62542c66d082SStefano 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);
6255f34684f1SStefano Zampini       }
6256f34684f1SStefano Zampini     }
6257019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6258b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
6259f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6260f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6261f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
6262f34684f1SStefano Zampini     }
6263f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6264f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6265e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6266e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6267f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
6268f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
6269b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
6270ca8b9ea9SStefano Zampini       PetscInt *gidxs;
6271ca8b9ea9SStefano Zampini 
6272ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
62733bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
6274f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
6275f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6276f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6277f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
62784bc2dc4bSStefano 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);
6279f34684f1SStefano Zampini       }
6280f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6281ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
6282f34684f1SStefano Zampini     }
6283f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
62841575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6285302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
6286f34684f1SStefano Zampini   }
62878bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
6288f34684f1SStefano Zampini   /* get back data */
6289f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
6290f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
6291674ae819SStefano Zampini   PetscFunctionReturn(0);
6292674ae819SStefano Zampini }
6293674ae819SStefano Zampini 
6294e456f2a8SStefano Zampini #undef __FUNCT__
6295e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
6296a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
6297e456f2a8SStefano Zampini {
6298e456f2a8SStefano Zampini   IS             localis_t;
6299a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
6300e456f2a8SStefano Zampini   PetscScalar    *vals;
6301e456f2a8SStefano Zampini   PetscErrorCode ierr;
6302e456f2a8SStefano Zampini 
6303e456f2a8SStefano Zampini   PetscFunctionBegin;
6304a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
6305e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
6306854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
6307e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
6308e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6309a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
6310a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
63111035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
6312a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
63131035eff8SStefano Zampini   }
6314a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
6315e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6316e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
6317a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
6318a7dc3881SStefano Zampini   /* now compute set in local ordering */
6319a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6320a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6321a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6322a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
6323a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6324ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6325e456f2a8SStefano Zampini       lsize++;
6326e456f2a8SStefano Zampini     }
6327e456f2a8SStefano Zampini   }
6328854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
6329a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6330ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6331e456f2a8SStefano Zampini       idxs[lsize++] = i;
6332e456f2a8SStefano Zampini     }
6333e456f2a8SStefano Zampini   }
6334a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6335a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
6336e456f2a8SStefano Zampini   *localis = localis_t;
6337e456f2a8SStefano Zampini   PetscFunctionReturn(0);
6338e456f2a8SStefano Zampini }
6339906d46d4SStefano Zampini 
6340b96c3477SStefano Zampini #undef __FUNCT__
6341b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
634208122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6343b96c3477SStefano Zampini {
6344a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6345b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6346b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6347a64f4aa4SStefano Zampini   Mat                 S_j;
6348b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6349b96c3477SStefano Zampini   PetscBool           free_used_adj;
6350b96c3477SStefano Zampini   PetscErrorCode      ierr;
6351b96c3477SStefano Zampini 
6352b96c3477SStefano Zampini   PetscFunctionBegin;
6353b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6354b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
635508122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6356b96c3477SStefano Zampini     used_xadj = NULL;
6357b96c3477SStefano Zampini     used_adjncy = NULL;
6358b96c3477SStefano Zampini   } else {
635908122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
636008122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
636108122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
636208122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6363b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6364b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6365b96c3477SStefano Zampini     } else {
63662fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6367b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6368b96c3477SStefano Zampini       PetscInt       nvtxs;
6369b96c3477SStefano Zampini 
63702fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
63712fffb893SStefano Zampini       if (flg_row) {
6372b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6373b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6374b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6375b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
63762fffb893SStefano Zampini       } else {
63772fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
63782fffb893SStefano Zampini         used_xadj = NULL;
63792fffb893SStefano Zampini         used_adjncy = NULL;
63802fffb893SStefano Zampini       }
63812fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6382b96c3477SStefano Zampini     }
6383b96c3477SStefano Zampini   }
6384d5574798SStefano Zampini 
6385d5574798SStefano Zampini   /* setup sub_schurs data */
6386a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6387df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6388df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6389a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
639091af6908SStefano 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);
6391a64f4aa4SStefano Zampini   } else {
63926816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
6393b7ab4a40SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;;
6394a3df083aSStefano Zampini     PetscInt  benign_n;
639572b8c272SStefano Zampini     Mat       change = NULL;
63969d54b7f4SStefano Zampini     Vec       scaling = NULL;
639772b8c272SStefano Zampini     IS        change_primal = NULL;
6398a3df083aSStefano Zampini 
63995feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
64005feab87aSStefano Zampini       PetscInt n_vertices;
64015feab87aSStefano Zampini 
64025feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
64032034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
64045feab87aSStefano Zampini     }
640504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
640604708bb6SStefano Zampini     if (!isseqaij) {
640704708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
640804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
640904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
641004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
641104708bb6SStefano Zampini       } else {
6412511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
641304708bb6SStefano Zampini       }
641404708bb6SStefano Zampini     }
6415a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6416a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6417ca92afb2SStefano Zampini     } else {
6418a3df083aSStefano Zampini       benign_n = 0;
6419ca92afb2SStefano Zampini     }
6420b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
6421b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
6422b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
642372b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
642422db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
6425b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
642622db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
6427b7ab4a40SStefano Zampini     }
6428b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
6429b7ab4a40SStefano 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 */
6430b7ab4a40SStefano Zampini     if (need_change) {
643188c03ad3SStefano Zampini       PC_IS   *pcisf;
643288c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
643388c03ad3SStefano Zampini       PC      pcf;
643488c03ad3SStefano Zampini 
6435e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
643688c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
643788c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
643888c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
643988c03ad3SStefano Zampini       /* hacks */
644088c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
644172b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
644272b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
644372b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
644472b8c272SStefano Zampini       pcisf->n = pcis->n;
644572b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
644688c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
644788c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
644888c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
644988c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
645088c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
645188c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
645272b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
645388c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
645488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
645572b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
645672b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
645772b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
645872b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
645972b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
646088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
646172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
646288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
646388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
646488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
646588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
646688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
646788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
646888c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
646988c03ad3SStefano Zampini     }
64709d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
647191af6908SStefano 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);
647272b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
647372b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
6474ca92afb2SStefano Zampini   }
6475d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6476b96c3477SStefano Zampini 
6477b96c3477SStefano Zampini   /* free adjacency */
6478b96c3477SStefano Zampini   if (free_used_adj) {
6479b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6480b96c3477SStefano Zampini   }
6481b96c3477SStefano Zampini   PetscFunctionReturn(0);
6482b96c3477SStefano Zampini }
6483b96c3477SStefano Zampini 
6484b96c3477SStefano Zampini #undef __FUNCT__
6485b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
648608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6487b96c3477SStefano Zampini {
6488b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6489b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6490b96c3477SStefano Zampini   PCBDDCGraph         graph;
6491b96c3477SStefano Zampini   PetscErrorCode      ierr;
6492b96c3477SStefano Zampini 
6493b96c3477SStefano Zampini   PetscFunctionBegin;
6494b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
649508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
64963301b35fSStefano Zampini     IS       verticesIS,verticescomm;
64973301b35fSStefano Zampini     PetscInt vsize,*idxs;
6498b96c3477SStefano Zampini 
6499b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
65003301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
65013301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
65023301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
65033301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
65043301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6505b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
65067fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
6507441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
65083301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6509b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6510b96c3477SStefano Zampini   } else {
6511b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6512b96c3477SStefano Zampini   }
6513e4d548c7SStefano Zampini   /* print some info */
6514e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
6515e4d548c7SStefano Zampini     IS       vertices;
6516e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
6517e4d548c7SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6518e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
6519e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
6520e4d548c7SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
6521e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6522e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6523e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
6524e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
6525e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
6526e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6527e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6528e4d548c7SStefano Zampini   }
6529b96c3477SStefano Zampini 
6530b96c3477SStefano Zampini   /* sub_schurs init */
6531*b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
6532*b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
6533*b334f244SStefano Zampini   }
6534*b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6535a64f4aa4SStefano Zampini 
6536b96c3477SStefano Zampini   /* free graph struct */
653708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6538b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6539b96c3477SStefano Zampini   }
6540b96c3477SStefano Zampini   PetscFunctionReturn(0);
6541b96c3477SStefano Zampini }
6542fa34dd3eSStefano Zampini 
6543fa34dd3eSStefano Zampini #undef __FUNCT__
6544fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6545fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6546fa34dd3eSStefano Zampini {
6547fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6548fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6549fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6550fa34dd3eSStefano Zampini 
6551fa34dd3eSStefano Zampini   PetscFunctionBegin;
6552fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6553fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
65544f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6555fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
65564f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
655775c01103SStefano Zampini     PetscReal      norm;
6558fa34dd3eSStefano Zampini     PetscInt       i;
6559fa34dd3eSStefano Zampini 
6560fa34dd3eSStefano Zampini     /* B0 and B0_B */
6561fa34dd3eSStefano Zampini     if (zerodiag) {
6562fa34dd3eSStefano Zampini       IS       dummy;
6563fa34dd3eSStefano Zampini 
65644f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
65654f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6566fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6567fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6568fa34dd3eSStefano Zampini     }
6569fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6570fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6571fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6572fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6573fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6574fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6575fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6576fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6577fa34dd3eSStefano Zampini     /* S_j */
6578fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6579fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6580fa34dd3eSStefano Zampini 
6581fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6582fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6583fa34dd3eSStefano Zampini     /* continuous in primal space */
6584fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6585fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6586fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6587fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
65884f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
65894f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6590fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6591fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6592fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6593fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6594fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6595fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6596fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6597fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6598fa34dd3eSStefano Zampini 
6599fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6600fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6601fa34dd3eSStefano Zampini     /* local with Schur */
6602fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6603fa34dd3eSStefano Zampini     if (zerodiag) {
6604fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
66054f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6606fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6607fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6608fa34dd3eSStefano Zampini     }
6609fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6610fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6611fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6612fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6613fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6614fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6615fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6616fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6617fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6618fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6619fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6620fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6621fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6622fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6623fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6624fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6625fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6626fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6627fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6628fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6629fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6630fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6631fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6632fa34dd3eSStefano Zampini     if (zerodiag) {
6633fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6634fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
66354f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6636fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6637fa34dd3eSStefano Zampini     }
6638fa34dd3eSStefano Zampini     /* BDDC */
6639fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6640fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6641fa34dd3eSStefano Zampini 
6642fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6643fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6644fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6645fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
66464f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
66474f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6648fa34dd3eSStefano Zampini     }
66494f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6650fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6651fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6652fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6653fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6654fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6655fa34dd3eSStefano Zampini   }
6656fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6657fa34dd3eSStefano Zampini }
6658