xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 3e589ea0e9468cbd6894e5503865077280f0601a)
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__
58*3e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
59*3e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
60*3e589ea0SStefano Zampini {
61*3e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
62*3e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
63*3e589ea0SStefano Zampini   PetscErrorCode    ierr;
64*3e589ea0SStefano Zampini 
65*3e589ea0SStefano Zampini   PetscFunctionBegin;
66*3e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
67*3e589ea0SStefano Zampini     PetscFunctionReturn(0);
68*3e589ea0SStefano Zampini   }
69*3e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
70*3e589ea0SStefano Zampini     Vec swap;
71*3e589ea0SStefano Zampini 
72*3e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
73*3e589ea0SStefano Zampini     swap = pcbddc->work_change;
74*3e589ea0SStefano Zampini     pcbddc->work_change = r;
75*3e589ea0SStefano Zampini     r = swap;
76*3e589ea0SStefano Zampini   }
77*3e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
78*3e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
79*3e589ea0SStefano Zampini   if (pcbddc->benign_n) {
80*3e589ea0SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
81*3e589ea0SStefano Zampini   } else {
82*3e589ea0SStefano Zampini     ierr = VecSet(pcis->vec2_D,0.);CHKERRQ(ierr);
83*3e589ea0SStefano Zampini   }
84*3e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
85*3e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
86*3e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
87*3e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
88*3e589ea0SStefano Zampini     Vec swap;
89*3e589ea0SStefano Zampini 
90*3e589ea0SStefano Zampini     swap = r;
91*3e589ea0SStefano Zampini     r = pcbddc->work_change;
92*3e589ea0SStefano Zampini     pcbddc->work_change = swap;
93*3e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
94*3e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
95*3e589ea0SStefano Zampini   }
96*3e589ea0SStefano Zampini   PetscFunctionReturn(0);
97*3e589ea0SStefano Zampini }
98*3e589ea0SStefano Zampini 
99*3e589ea0SStefano 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;
224df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs->reuse_solver;
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;
1140af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
1141af25d912SStefano 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);
114206a4e24aSStefano Zampini 
1143fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1144fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1145fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1146fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
11471575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1148fd14bc51SStefano Zampini   }
1149fd14bc51SStefano Zampini 
1150e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
1151e496cd5dSStefano 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);
1152e496cd5dSStefano Zampini   }
1153e496cd5dSStefano Zampini 
115408122e43SStefano Zampini   /* max size of subsets */
115508122e43SStefano Zampini   mss = 0;
115608122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
115708122e43SStefano Zampini     PetscInt subset_size;
1158862806e4SStefano Zampini 
115908122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
116008122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
116108122e43SStefano Zampini   }
116208122e43SStefano Zampini 
116308122e43SStefano Zampini   /* min/max and threshold */
116408122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
1165f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
116608122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
1167f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
1168f6f667cfSStefano Zampini   if (nmin) {
1169f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
1170f6f667cfSStefano Zampini   }
117108122e43SStefano Zampini 
117208122e43SStefano Zampini   /* allocate lapack workspace */
117308122e43SStefano Zampini   cum = cum2 = 0;
117408122e43SStefano Zampini   maxneigs = 0;
117508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
117608122e43SStefano Zampini     PetscInt n,subset_size;
1177f6f667cfSStefano Zampini 
117808122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
117908122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
11809162d606SStefano Zampini     cum += subset_size;
11819162d606SStefano Zampini     cum2 += subset_size*n;
118208122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
118308122e43SStefano Zampini   }
118408122e43SStefano Zampini   if (mss) {
11859ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
118608122e43SStefano Zampini       PetscBLASInt B_itype = 1;
118708122e43SStefano Zampini       PetscBLASInt B_N = mss;
11884c6709b3SStefano Zampini       PetscReal    zero = 0.0;
11894c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
119008122e43SStefano Zampini 
119108122e43SStefano Zampini       B_lwork = -1;
119208122e43SStefano Zampini       S = NULL;
119308122e43SStefano Zampini       St = NULL;
1194a58a30b4SStefano Zampini       eigs = NULL;
1195a58a30b4SStefano Zampini       eigv = NULL;
1196a58a30b4SStefano Zampini       B_iwork = NULL;
1197a58a30b4SStefano Zampini       B_ifail = NULL;
1198d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1199d1710679SStefano Zampini       rwork = NULL;
1200d1710679SStefano Zampini #endif
12018bec7fa6SStefano Zampini       thresh = 1.0;
120208122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
120308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
120408122e43SStefano 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));
120508122e43SStefano Zampini #else
120608122e43SStefano 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));
120708122e43SStefano Zampini #endif
120808122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
120908122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
121008122e43SStefano Zampini     } else {
121108122e43SStefano Zampini         /* TODO */
121208122e43SStefano Zampini     }
121308122e43SStefano Zampini   } else {
121408122e43SStefano Zampini     lwork = 0;
121508122e43SStefano Zampini   }
121608122e43SStefano Zampini 
121708122e43SStefano Zampini   nv = 0;
1218d62866d3SStefano 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) */
1219d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
122008122e43SStefano Zampini   }
12214c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
1222f6f667cfSStefano Zampini   if (allocated_S_St) {
1223f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
1224f6f667cfSStefano Zampini   }
1225f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
122608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
122708122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
122808122e43SStefano Zampini #endif
12299162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
12309162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
12319162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
123208122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
12339162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
123408122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
123508122e43SStefano Zampini 
123608122e43SStefano Zampini   maxneigs = 0;
123772b8c272SStefano Zampini   cum = cumarray = 0;
12389162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
12399162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
1240d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
124108122e43SStefano Zampini     const PetscInt *idxs;
124208122e43SStefano Zampini 
1243d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
124408122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
124508122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
124608122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
124708122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
12489162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
12499162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
125008122e43SStefano Zampini     }
1251d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
125208122e43SStefano Zampini   }
125308122e43SStefano Zampini 
125408122e43SStefano Zampini   if (mss) { /* multilevel */
125508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
125608122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
125708122e43SStefano Zampini   }
125808122e43SStefano Zampini 
1259ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
126008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
126108122e43SStefano Zampini     const PetscInt *idxs;
12629d54b7f4SStefano Zampini     PetscReal      upper,lower;
1263862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
126408122e43SStefano Zampini     PetscBLASInt   B_N;
1265aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
126608122e43SStefano Zampini 
12679d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
12689d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
12699d54b7f4SStefano Zampini       lower = thresh;
12709d54b7f4SStefano Zampini     } else {
12719d54b7f4SStefano Zampini       upper = 1./thresh;
12729d54b7f4SStefano Zampini       lower = 0.;
12739d54b7f4SStefano Zampini     }
1274862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
1275ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
1276f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
1277f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
12789ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
1279aff50787SStefano Zampini         PetscInt j,k;
1280aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
1281aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1282aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
128308122e43SStefano Zampini         }
128408122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1285aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1286aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1287aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1288aff50787SStefano Zampini           }
128908122e43SStefano Zampini         }
129008122e43SStefano Zampini       } else {
129108122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
129208122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
129308122e43SStefano Zampini       }
12948bec7fa6SStefano Zampini     } else {
1295f6f667cfSStefano Zampini       S = Sarray + cumarray;
1296f6f667cfSStefano Zampini       St = Starray + cumarray;
12978bec7fa6SStefano Zampini     }
1298aff50787SStefano Zampini     /* see if we can save some work */
1299b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
1300aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1301aff50787SStefano Zampini     }
1302aff50787SStefano Zampini 
1303b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
1304aff50787SStefano Zampini       B_neigs = 0;
1305aff50787SStefano Zampini     } else {
13069ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
130708122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1308f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
13094c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
13109552c7c7SStefano Zampini         PetscInt     nmin_s;
1311b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
131208122e43SStefano Zampini 
1313fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
13148bec7fa6SStefano 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]]);
1315fd14bc51SStefano Zampini         }
1316d16cbb6bSStefano Zampini 
1317b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
1318b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
1319b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
1320b7ab4a40SStefano Zampini         }
1321b7ab4a40SStefano Zampini 
132208122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1323b7ab4a40SStefano Zampini         if (compute_range) {
1324d16cbb6bSStefano Zampini 
1325d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
132608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
13279d54b7f4SStefano 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));
132808122e43SStefano Zampini #else
13299d54b7f4SStefano 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));
133008122e43SStefano Zampini #endif
1331b7ab4a40SStefano Zampini         } else if (!same_data) {
1332d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1333d16cbb6bSStefano Zampini           B_IL = 1;
1334d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
13359d54b7f4SStefano 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));
1336d16cbb6bSStefano Zampini #else
13379d54b7f4SStefano 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));
1338d16cbb6bSStefano Zampini #endif
1339b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
1340b7ab4a40SStefano Zampini           PetscInt k;
1341b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
1342b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
1343b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
1344b7ab4a40SStefano Zampini           nmin = nmax;
1345b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1346b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
1347b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
1348b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
1349b7ab4a40SStefano Zampini           }
1350d16cbb6bSStefano Zampini         }
135108122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
135208122e43SStefano Zampini         if (B_ierr) {
13536c4ed002SBarry 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);
13546c4ed002SBarry 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);
13556c4ed002SBarry 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);
135608122e43SStefano Zampini         }
135708122e43SStefano Zampini 
135808122e43SStefano Zampini         if (B_neigs > nmax) {
1359fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1360fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1361fd14bc51SStefano Zampini           }
13629d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
136308122e43SStefano Zampini           B_neigs = nmax;
136408122e43SStefano Zampini         }
136508122e43SStefano Zampini 
13669552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
13679552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
136808122e43SStefano Zampini           PetscBLASInt B_neigs2;
136908122e43SStefano Zampini 
13709d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
1371f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
13729d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
13739d54b7f4SStefano Zampini           } else {
13749d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
13759d54b7f4SStefano Zampini             B_IU = nmin_s;
13769d54b7f4SStefano Zampini           }
1377fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1378fd14bc51SStefano 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);
1379fd14bc51SStefano Zampini           }
13809ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
138108122e43SStefano Zampini             PetscInt j;
138208122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
138308122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
138408122e43SStefano Zampini             }
138508122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
138608122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
138708122e43SStefano Zampini             }
138808122e43SStefano Zampini           } else {
138908122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139008122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139108122e43SStefano Zampini           }
139208122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
139308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
13949d54b7f4SStefano 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));
139508122e43SStefano Zampini #else
13969d54b7f4SStefano 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));
139708122e43SStefano Zampini #endif
139808122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
139908122e43SStefano Zampini           B_neigs += B_neigs2;
140008122e43SStefano Zampini         }
140108122e43SStefano Zampini         if (B_ierr) {
14026c4ed002SBarry 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);
14036c4ed002SBarry 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);
14046c4ed002SBarry 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);
140508122e43SStefano Zampini         }
1406fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1407ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
140808122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
140908122e43SStefano Zampini             if (eigs[j] == 0.0) {
1410ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
141108122e43SStefano Zampini             } else {
14129d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
1413ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
14149d54b7f4SStefano Zampini               } else {
14159d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
14169d54b7f4SStefano Zampini               }
1417fd14bc51SStefano Zampini             }
141808122e43SStefano Zampini           }
141908122e43SStefano Zampini         }
142008122e43SStefano Zampini       } else {
142108122e43SStefano Zampini           /* TODO */
142208122e43SStefano Zampini       }
1423aff50787SStefano Zampini     }
14246c3e6151SStefano Zampini     /* change the basis back to the original one */
14256c3e6151SStefano Zampini     if (sub_schurs->change) {
142672b8c272SStefano Zampini       Mat change,phi,phit;
14276c3e6151SStefano Zampini 
14286c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
14296c3e6151SStefano Zampini         PetscInt ii;
14306c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
14316c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
14326c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
14336c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
14346c3e6151SStefano Zampini           }
14356c3e6151SStefano Zampini         }
14366c3e6151SStefano Zampini       }
143772b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
14386c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
143972b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
14406c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
14416c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
14426c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
14436c3e6151SStefano Zampini     }
14448bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
14458bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
14469162d606SStefano Zampini     if (B_neigs) {
14479162d606SStefano 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);
1448fd14bc51SStefano Zampini 
1449fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
14509552c7c7SStefano Zampini         PetscInt ii;
14519552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1452ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
14539552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1454ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1455ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1456ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1457ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1458ac47001eSStefano Zampini #else
1459ac47001eSStefano 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);
1460ac47001eSStefano Zampini #endif
14619552c7c7SStefano Zampini           }
14629552c7c7SStefano Zampini         }
1463fd14bc51SStefano Zampini       }
14649162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
14659162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
14669162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
14679162d606SStefano Zampini       cum++;
146808122e43SStefano Zampini     }
146908122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
147008122e43SStefano Zampini     /* shift for next computation */
147108122e43SStefano Zampini     cumarray += subset_size*subset_size;
147208122e43SStefano Zampini   }
1473fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1474fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1475fd14bc51SStefano Zampini   }
147608122e43SStefano Zampini 
147708122e43SStefano Zampini   if (mss) {
147808122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
147908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1480f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1481f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1482f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
148308122e43SStefano Zampini   }
1484f6f667cfSStefano Zampini   if (allocated_S_St) {
1485f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1486f6f667cfSStefano Zampini   }
1487f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
148808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
148908122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
149008122e43SStefano Zampini #endif
149108122e43SStefano Zampini   if (pcbddc->dbg_flag) {
14921b968477SStefano Zampini     PetscInt maxneigs_r;
1493b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
14949b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
149508122e43SStefano Zampini   }
149608122e43SStefano Zampini   PetscFunctionReturn(0);
149708122e43SStefano Zampini }
1498b1b3d7a2SStefano Zampini 
1499674ae819SStefano Zampini #undef __FUNCT__
1500c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1501c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1502c8587f34SStefano Zampini {
1503c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
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 
1516c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1517b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
1518c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1519c8587f34SStefano Zampini   }
1520c8587f34SStefano Zampini 
15218629588bSStefano Zampini   /*
15228629588bSStefano Zampini      Setup local correction and local part of coarse basis.
15238629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
15248629588bSStefano Zampini   */
152547f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
15268629588bSStefano Zampini 
15278629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
15288629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
15298629588bSStefano Zampini 
15308629588bSStefano Zampini   /* free */
15318629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1532c8587f34SStefano Zampini   PetscFunctionReturn(0);
1533c8587f34SStefano Zampini }
1534c8587f34SStefano Zampini 
1535c8587f34SStefano Zampini #undef __FUNCT__
1536674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1537674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1538674ae819SStefano Zampini {
1539674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1540674ae819SStefano Zampini   PetscErrorCode ierr;
1541674ae819SStefano Zampini 
1542674ae819SStefano Zampini   PetscFunctionBegin;
1543674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1544674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
154530368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1546674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
1547674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1548785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1549674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1550f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1551f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1552785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
155363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
155463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1555674ae819SStefano Zampini   PetscFunctionReturn(0);
1556674ae819SStefano Zampini }
1557674ae819SStefano Zampini 
1558674ae819SStefano Zampini #undef __FUNCT__
1559674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1560674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1561674ae819SStefano Zampini {
1562674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15634f1b2e48SStefano Zampini   PetscInt       i;
1564674ae819SStefano Zampini   PetscErrorCode ierr;
1565674ae819SStefano Zampini 
1566674ae819SStefano Zampini   PetscFunctionBegin;
1567b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1568674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
156916909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
15701dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
1571674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1572674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
15734f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
15744f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
15754f1b2e48SStefano Zampini   }
15764f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1577b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1578674ae819SStefano Zampini   PetscFunctionReturn(0);
1579674ae819SStefano Zampini }
1580674ae819SStefano Zampini 
1581674ae819SStefano Zampini #undef __FUNCT__
1582674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1583674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1584674ae819SStefano Zampini {
1585674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1586674ae819SStefano Zampini   PetscErrorCode ierr;
1587674ae819SStefano Zampini 
1588674ae819SStefano Zampini   PetscFunctionBegin;
1589674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
159058da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1591ca92afb2SStefano Zampini     PetscScalar *array;
159206656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
159306656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
159458da7f69SStefano Zampini   }
1595674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1596674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
159715aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
159815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1599674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1600674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1601674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
160206656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1603674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1604674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
16058ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1606674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1607674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1608674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1609f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1610f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1611f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1612f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1613727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
16140e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1615f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
161670cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
161781d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
16180369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
16191dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
16204f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
16218b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1622ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1623ca92afb2SStefano Zampini     PetscInt i;
1624ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1625ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1626ca92afb2SStefano Zampini     }
1627ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1628ca92afb2SStefano Zampini   }
16294f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1630674ae819SStefano Zampini   PetscFunctionReturn(0);
1631674ae819SStefano Zampini }
1632674ae819SStefano Zampini 
1633674ae819SStefano Zampini #undef __FUNCT__
1634f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1635f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
16366bfb1811SStefano Zampini {
16376bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16386bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
16396bfb1811SStefano Zampini   VecType        impVecType;
16404f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
16416bfb1811SStefano Zampini   PetscErrorCode ierr;
16426bfb1811SStefano Zampini 
16436bfb1811SStefano Zampini   PetscFunctionBegin;
16446c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1645e7b262bdSStefano Zampini   /* get sizes */
16464f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1647b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
16486bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1649e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1650e7b262bdSStefano Zampini   /* R nodes */
1651e7b262bdSStefano Zampini   old_size = -1;
1652e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1653e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1654e7b262bdSStefano Zampini   }
1655e7b262bdSStefano Zampini   if (n_R != old_size) {
1656e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1657e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
16586bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
16596bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
16606bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
16616bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1662e7b262bdSStefano Zampini   }
1663e7b262bdSStefano Zampini   /* local primal dofs */
1664e7b262bdSStefano Zampini   old_size = -1;
1665e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1666e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1667e7b262bdSStefano Zampini   }
1668e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1669e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
167083b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1671e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
16726bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1673e7b262bdSStefano Zampini   }
1674e7b262bdSStefano Zampini   /* local explicit constraints */
1675e7b262bdSStefano Zampini   old_size = -1;
1676e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1677e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1678e7b262bdSStefano Zampini   }
1679e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1680e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
168183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
168283b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
168383b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
168483b7ccabSStefano Zampini   }
16856bfb1811SStefano Zampini   PetscFunctionReturn(0);
16866bfb1811SStefano Zampini }
16876bfb1811SStefano Zampini 
16886bfb1811SStefano Zampini #undef __FUNCT__
168947f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
169047f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
169188ebb749SStefano Zampini {
169225084f0cSStefano Zampini   PetscErrorCode  ierr;
169325084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
169488ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
169588ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1696d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
169725084f0cSStefano Zampini   /* submatrices of local problem */
169880677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
169906656605SStefano Zampini   /* submatrices of local coarse problem */
170006656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
170125084f0cSStefano Zampini   /* working matrices */
170206656605SStefano Zampini   Mat             C_CR;
170325084f0cSStefano Zampini   /* additional working stuff */
170406656605SStefano Zampini   PC              pc_R;
17054f1b2e48SStefano Zampini   Mat             F;
17065cbda25cSStefano Zampini   Vec             dummy_vec;
1707a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
170825084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
170906656605SStefano Zampini   PetscScalar     *work;
171006656605SStefano Zampini   PetscInt        *idx_V_B;
1711ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
171206656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1713ffd830a3SStefano Zampini 
171425084f0cSStefano Zampini   /* some shortcuts to scalars */
171506656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
171688ebb749SStefano Zampini 
171788ebb749SStefano Zampini   PetscFunctionBegin;
1718ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1719ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1720ffd830a3SStefano Zampini   }
1721ffd830a3SStefano Zampini 
1722ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1723b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
17244f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1725b371cd4fSStefano Zampini   n_B = pcis->n_B;
1726b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
172788ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
172888ebb749SStefano Zampini 
172988ebb749SStefano Zampini   /* vertices in boundary numbering */
1730785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
17310e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
17326c4ed002SBarry 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);
173388ebb749SStefano Zampini 
173406656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1735019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
173606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
173706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
173806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
173906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
174006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
174106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
174206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
174306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
174406656605SStefano Zampini 
174506656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
174606656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
174706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
174806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
174906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1750ffd830a3SStefano Zampini   lda_rhs = n_R;
1751a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
175206656605SStefano Zampini   if (isLU || isILU || isCHOL) {
175306656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1754df4d28bfSStefano Zampini   } else if (sub_schurs->reuse_solver) {
1755df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1756d62866d3SStefano Zampini     MatFactorType      type;
1757d62866d3SStefano Zampini 
1758df4d28bfSStefano Zampini     F = reuse_solver->F;
17596816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1760d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1761ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
176222db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
176306656605SStefano Zampini   } else {
176406656605SStefano Zampini     F = NULL;
176506656605SStefano Zampini   }
176606656605SStefano Zampini 
1767ffd830a3SStefano Zampini   /* allocate workspace */
1768ffd830a3SStefano Zampini   n = 0;
1769ffd830a3SStefano Zampini   if (n_constraints) {
1770ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1771ffd830a3SStefano Zampini   }
1772ffd830a3SStefano Zampini   if (n_vertices) {
1773ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1774ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1775ffd830a3SStefano Zampini   }
1776ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1777ffd830a3SStefano Zampini 
17785cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
17795cbda25cSStefano Zampini   dummy_vec = NULL;
17805cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
17815cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
17825cbda25cSStefano Zampini   }
17835cbda25cSStefano Zampini 
178488ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
178588ebb749SStefano Zampini   if (n_constraints) {
178672b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
178706656605SStefano Zampini     IS          is_aux;
178880677318SStefano Zampini     PetscScalar *array,*array2;
178906656605SStefano Zampini 
1790f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
179180677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
179288ebb749SStefano Zampini 
179325084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
179425084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
17958ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
179672b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
179788ebb749SStefano Zampini 
179880677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
179980677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1800ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
180188ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
180206656605SStefano Zampini       const PetscScalar *row_cmat_values;
180306656605SStefano Zampini       const PetscInt    *row_cmat_indices;
180406656605SStefano Zampini       PetscInt          size_of_constraint,j;
180588ebb749SStefano Zampini 
180606656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
180706656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1808ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
180906656605SStefano Zampini       }
181006656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
181106656605SStefano Zampini     }
1812ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
181306656605SStefano Zampini     if (F) {
181406656605SStefano Zampini       Mat B;
181506656605SStefano Zampini 
1816ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1817a3df083aSStefano Zampini       if (need_benign_correction) {
1818df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1819a3df083aSStefano Zampini 
182072b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
182172b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1822a3df083aSStefano Zampini       }
182380677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1824a3df083aSStefano Zampini       if (need_benign_correction) {
1825a3df083aSStefano Zampini         PetscScalar        *marr;
1826df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1827a3df083aSStefano Zampini 
1828a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
18295cbda25cSStefano Zampini         if (lda_rhs != n_R) {
18305cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
18315cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
18325cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
18335cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
18345cbda25cSStefano Zampini           }
18355cbda25cSStefano Zampini         } else {
1836a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
1837a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
18385cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
1839a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1840a3df083aSStefano Zampini           }
18415cbda25cSStefano Zampini         }
1842a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1843a3df083aSStefano Zampini       }
184406656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
184506656605SStefano Zampini     } else {
184680677318SStefano Zampini       PetscScalar *marr;
184780677318SStefano Zampini 
184880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
184906656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1850ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1851ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
185206656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
185306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
185406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
185506656605SStefano Zampini       }
185680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
185706656605SStefano Zampini     }
185880677318SStefano Zampini     if (!pcbddc->switch_static) {
185980677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
186080677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
186180677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
186280677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1863ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
186480677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
186580677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
186680677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
186780677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
186880677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
186980677318SStefano Zampini       }
187080677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
187180677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
187272b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
187380677318SStefano Zampini     } else {
1874ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1875ffd830a3SStefano Zampini         IS dummy;
1876ffd830a3SStefano Zampini 
1877ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
187872b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1879ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1880ffd830a3SStefano Zampini       } else {
188180677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
188280677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1883ffd830a3SStefano Zampini       }
188425084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
188580677318SStefano Zampini     }
188680677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
188780677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
188880677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
188906656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
189006656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
189180677318SStefano Zampini     if (isCHOL) {
189280677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
189380677318SStefano Zampini     } else {
189425084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
189580677318SStefano Zampini     }
189680677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
189706656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
189825084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
189925084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
190025084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
190180677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
190272b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
190372b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
190406656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
190506656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1906f4ddd8eeSStefano Zampini   }
1907fc227af8SStefano Zampini 
1908fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
190988ebb749SStefano Zampini   if (n_vertices) {
191006656605SStefano Zampini     IS is_aux;
19113a50541eSStefano Zampini 
1912df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
19136816873aSStefano Zampini       IS tis;
19146816873aSStefano Zampini 
19156816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
19166816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
19176816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
19186816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
19196816873aSStefano Zampini     } else {
19203a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
19216816873aSStefano Zampini     }
19229577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
19239577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
192404708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
192525084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
192688ebb749SStefano Zampini   }
192788ebb749SStefano Zampini 
192888ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1929f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
193006656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
193106656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
193206656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
193306656605SStefano Zampini     }
1934f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
193506656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
193606656605SStefano Zampini       PetscScalar *marray;
193706656605SStefano Zampini 
193806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
193906656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1940f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1941f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1942f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1943f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1944f4ddd8eeSStefano Zampini     }
1945f4ddd8eeSStefano Zampini   }
194606656605SStefano Zampini 
1947f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
194806656605SStefano Zampini     PetscScalar *marray;
194988ebb749SStefano Zampini 
195006656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
19518eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
195206656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
195388ebb749SStefano Zampini     }
19543301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
195506656605SStefano Zampini       n *= 2;
195688ebb749SStefano Zampini     }
195706656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
195806656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
195906656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
19608eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
196106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
196206656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
196388ebb749SStefano Zampini     }
19643301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
196506656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
19668eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
196706656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
196806656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
196988ebb749SStefano Zampini       }
197088ebb749SStefano Zampini     } else {
1971c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1972c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
19731b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1974c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1975c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1976c0553b1fSStefano Zampini       }
197788ebb749SStefano Zampini     }
197806656605SStefano Zampini   }
1979019a44ceSStefano Zampini 
198006656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
19814f1b2e48SStefano Zampini   p0_lidx_I = NULL;
19824f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1983d12edf2fSStefano Zampini     const PetscInt *idxs;
1984d12edf2fSStefano Zampini 
1985d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
19864f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
19874f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
19884f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
19894f1b2e48SStefano Zampini     }
1990d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1991d12edf2fSStefano Zampini   }
1992d16cbb6bSStefano Zampini 
199306656605SStefano Zampini   /* vertices */
199406656605SStefano Zampini   if (n_vertices) {
199516f15bc4SStefano Zampini 
1996af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
199704708bb6SStefano Zampini 
199816f15bc4SStefano Zampini     if (n_R) {
199914393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
200006656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
200116f15bc4SStefano Zampini       PetscScalar  *x,*y;
200204708bb6SStefano Zampini       PetscBool    isseqaij;
200306656605SStefano Zampini 
200421eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
200514393ed6SStefano Zampini       if (need_benign_correction) {
200614393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
200714393ed6SStefano Zampini         IS                     is_p0;
200814393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
200914393ed6SStefano Zampini 
201014393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
201114393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
201214393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
2013af25d912SStefano 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);
201414393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
201514393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
201614393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
201714393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
201814393ed6SStefano Zampini       }
201914393ed6SStefano Zampini 
2020ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
2021af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2022ffd830a3SStefano Zampini       } else {
2023ca92afb2SStefano Zampini         PetscScalar    *av,*array;
2024ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
2025ca92afb2SStefano Zampini         PetscInt       n;
2026ca92afb2SStefano Zampini         PetscBool      flg_row;
2027ffd830a3SStefano Zampini 
2028ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
2029ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
20309d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2031ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2032ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
2033ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
2034ca92afb2SStefano Zampini           PetscInt j;
2035ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
2036ffd830a3SStefano Zampini         }
2037ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2038ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2039ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
2040ffd830a3SStefano Zampini       }
2041ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2042a3df083aSStefano Zampini       if (need_benign_correction) {
2043df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2044a3df083aSStefano Zampini         PetscScalar        *marr;
2045a3df083aSStefano Zampini 
2046a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
204714393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
204814393ed6SStefano Zampini 
204914393ed6SStefano Zampini                | 0 0  0 | (V)
205014393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
205114393ed6SStefano Zampini                | 0 0 -1 | (p0)
205214393ed6SStefano Zampini 
205314393ed6SStefano Zampini         */
2054df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
205514393ed6SStefano Zampini           const PetscScalar *vals;
205614393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
205714393ed6SStefano Zampini           PetscInt          n,j,nz;
205814393ed6SStefano Zampini 
2059df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2060df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
206114393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
206214393ed6SStefano Zampini           for (j=0;j<n;j++) {
206314393ed6SStefano Zampini             PetscScalar val = vals[j];
206414393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
206514393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
206614393ed6SStefano Zampini           }
206714393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2068df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
206914393ed6SStefano Zampini         }
207072b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
207172b8c272SStefano Zampini       }
207272b8c272SStefano Zampini       if (F) {
207314393ed6SStefano Zampini         /* need to correct the rhs */
207472b8c272SStefano Zampini         if (need_benign_correction) {
207572b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
207672b8c272SStefano Zampini           PetscScalar        *marr;
207772b8c272SStefano Zampini 
207872b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
20795cbda25cSStefano Zampini           if (lda_rhs != n_R) {
20805cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
20815cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
20825cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
20835cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
20845cbda25cSStefano Zampini             }
20855cbda25cSStefano Zampini           } else {
2086a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2087a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
20885cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2089a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2090a3df083aSStefano Zampini             }
20915cbda25cSStefano Zampini           }
2092a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
2093a3df083aSStefano Zampini         }
209406656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
209514393ed6SStefano Zampini         /* need to correct the solution */
2096a3df083aSStefano Zampini         if (need_benign_correction) {
2097df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2098a3df083aSStefano Zampini           PetscScalar        *marr;
2099a3df083aSStefano Zampini 
2100a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
21015cbda25cSStefano Zampini           if (lda_rhs != n_R) {
21025cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
21035cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
21045cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
21055cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
21065cbda25cSStefano Zampini             }
21075cbda25cSStefano Zampini           } else {
2108a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2109a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
21105cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2111a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2112a3df083aSStefano Zampini             }
21135cbda25cSStefano Zampini           }
2114a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
2115a3df083aSStefano Zampini         }
211606656605SStefano Zampini       } else {
211706656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
211806656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
2119ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
2120ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
212106656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
212206656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
212306656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
212406656605SStefano Zampini         }
212506656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
212606656605SStefano Zampini       }
212780677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2128ffd830a3SStefano Zampini       /* S_VV and S_CV */
212906656605SStefano Zampini       if (n_constraints) {
213006656605SStefano Zampini         Mat B;
213180677318SStefano Zampini 
2132ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
213380677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
2134ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
2135ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
213680677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213780677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213880677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
213980677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
214080677318SStefano Zampini         }
2141ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
214280677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
214380677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
2144ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
214580677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
214606656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
2147ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
2148ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
214906656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
215006656605SStefano Zampini       }
215104708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
215204708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
2153511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
215404708bb6SStefano Zampini       }
2155ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
2156ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
2157ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2158ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
2159ffd830a3SStefano Zampini       }
216006656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
216114393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
216214393ed6SStefano Zampini       if (need_benign_correction) {
2163df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
216414393ed6SStefano Zampini         PetscScalar      *marr,*sums;
216514393ed6SStefano Zampini 
216614393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
216714393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
2168df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
216914393ed6SStefano Zampini           const PetscScalar *vals;
217014393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
217114393ed6SStefano Zampini           PetscInt          n,j,nz;
217214393ed6SStefano Zampini 
2173df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2174df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
217514393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
217614393ed6SStefano Zampini             PetscInt k;
217714393ed6SStefano Zampini             sums[j] = 0.;
217814393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
217914393ed6SStefano Zampini           }
218014393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
218114393ed6SStefano Zampini           for (j=0;j<n;j++) {
218214393ed6SStefano Zampini             PetscScalar val = vals[j];
218314393ed6SStefano Zampini             PetscInt k;
218414393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
218514393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
218614393ed6SStefano Zampini             }
218714393ed6SStefano Zampini           }
218814393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2189df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
219014393ed6SStefano Zampini         }
219114393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
219214393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
219314393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
219414393ed6SStefano Zampini       }
219580677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
219606656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
219706656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
219806656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
219906656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
220006656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
220106656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
220206656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2203d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
2204019a44ceSStefano Zampini     } else {
2205d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2206d16cbb6bSStefano Zampini     }
220721eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
2208d16cbb6bSStefano Zampini 
220906656605SStefano Zampini     /* coarse basis functions */
221006656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
221116f15bc4SStefano Zampini       PetscScalar *y;
221216f15bc4SStefano Zampini 
2213ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
221406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
221506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
221606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
221706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
221806656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
221906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
222006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
222106656605SStefano Zampini 
222206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
22234f1b2e48SStefano Zampini         PetscInt j;
22244f1b2e48SStefano Zampini 
222506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
222606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
222706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
222806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
222906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
22304f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
223106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
223206656605SStefano Zampini       }
223306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
223406656605SStefano Zampini     }
223504708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
223604708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
223706656605SStefano Zampini   }
22385cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
223906656605SStefano Zampini 
224006656605SStefano Zampini   if (n_constraints) {
224106656605SStefano Zampini     Mat B;
224206656605SStefano Zampini 
2243ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
224406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
224580677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
224606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
224706656605SStefano Zampini     if (n_vertices) {
224880677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
224980677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
225080677318SStefano Zampini       } else {
225180677318SStefano Zampini         Mat S_VCt;
225280677318SStefano Zampini 
2253ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
2254ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
225572b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
2256ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
2257ffd830a3SStefano Zampini         }
225880677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
225980677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
226080677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
226180677318SStefano Zampini       }
226206656605SStefano Zampini     }
226306656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
226406656605SStefano Zampini     /* coarse basis functions */
226506656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
226606656605SStefano Zampini       PetscScalar *y;
226706656605SStefano Zampini 
2268ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
226906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
227006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
227106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
227206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
227306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
227406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
227506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
22764f1b2e48SStefano Zampini         PetscInt j;
22774f1b2e48SStefano Zampini 
227806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
227906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
228006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
228106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
228206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
22834f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
228406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
228506656605SStefano Zampini       }
228606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
228706656605SStefano Zampini     }
228806656605SStefano Zampini   }
228980677318SStefano Zampini   if (n_constraints) {
229080677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
229180677318SStefano Zampini   }
22924f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
229372b8c272SStefano Zampini 
229472b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
229572b8c272SStefano Zampini   if (pcbddc->benign_n) {
229672b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
229772b8c272SStefano Zampini     IS          is_dummy;
229872b8c272SStefano Zampini     PetscScalar *data;
229972b8c272SStefano Zampini     PetscInt    j;
230072b8c272SStefano Zampini 
230172b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
230272b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
230372b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
230472b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
230586c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
230672b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
230772b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
230872b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
230972b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
231072b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
231172b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
231272b8c272SStefano Zampini       }
231372b8c272SStefano Zampini     }
231472b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
231572b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
231672b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
231772b8c272SStefano Zampini   }
2318019a44ceSStefano Zampini 
231906656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
23203301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
2321ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
2322ffd830a3SStefano Zampini     PetscScalar *marray;
232306656605SStefano Zampini 
232406656605SStefano Zampini     if (n_constraints) {
2325ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
232606656605SStefano Zampini 
2327af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
232806656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
2329ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
233016f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
233106656605SStefano Zampini       if (n_vertices) {
2332ffd830a3SStefano Zampini         Mat S_VCT;
233306656605SStefano Zampini 
233406656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
2335ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
233616f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
233706656605SStefano Zampini       }
2338ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
233906656605SStefano Zampini     }
234016f15bc4SStefano Zampini     if (n_vertices && n_R) {
2341ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2342ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2343ffd830a3SStefano Zampini       PetscInt       n;
2344ffd830a3SStefano Zampini       PetscBool      flg_row;
234506656605SStefano Zampini 
2346ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2347af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
2348ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2349ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2350ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2351ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2352ffd830a3SStefano Zampini         PetscInt j;
2353ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2354ffd830a3SStefano Zampini       }
2355ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2356ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2357ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
235806656605SStefano Zampini     }
235906656605SStefano Zampini 
2360ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2361ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2362ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2363ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2364ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
236506656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
236606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
236706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
236806656605SStefano Zampini     }
2369ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2370ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2371ffd830a3SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2372ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2373ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2374ffd830a3SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2375ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2376ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
237706656605SStefano Zampini     }
2378ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
237906656605SStefano Zampini     /* coarse basis functions */
238006656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
238106656605SStefano Zampini       PetscScalar *y;
238206656605SStefano Zampini 
2383ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
238406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
238506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
238606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238806656605SStefano Zampini       if (i<n_vertices) {
238906656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
239006656605SStefano Zampini       }
239106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
239206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
239306656605SStefano Zampini 
239406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
239506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
239606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
239706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
239806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
239906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
240006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
240106656605SStefano Zampini       }
240206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
240306656605SStefano Zampini     }
2404ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2405ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
240606656605SStefano Zampini   }
2407d62866d3SStefano Zampini   /* free memory */
240888ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
240906656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
241006656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
241106656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
241206656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2413d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2414d62866d3SStefano Zampini   if (n_vertices) {
2415d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2416d62866d3SStefano Zampini   }
2417d62866d3SStefano Zampini   if (n_constraints) {
2418d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2419d62866d3SStefano Zampini   }
242088ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
242188ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
242288ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2423d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
242488ebb749SStefano Zampini     Mat         coarse_sub_mat;
242525084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
242688ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
242788ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
242888ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
24298bec7fa6SStefano Zampini     Mat         C_B,CPHI;
24308bec7fa6SStefano Zampini     IS          is_dummy;
24318bec7fa6SStefano Zampini     Vec         mones;
243288ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
243388ebb749SStefano Zampini     PetscReal   real_value;
243488ebb749SStefano Zampini 
2435a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2436a3df083aSStefano Zampini       Mat A;
2437a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2438a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2439a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2440a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2441a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2442a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2443a3df083aSStefano Zampini     } else {
244488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
244588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
244688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
244788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2448a3df083aSStefano Zampini     }
244988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
245088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2451ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
245288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
245388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
245488ebb749SStefano Zampini     }
245588ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
245688ebb749SStefano Zampini 
245725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
24583301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
245925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2460ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
246188ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
246288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
246388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
246488ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
246588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
246688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
246788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
246888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
246988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
247088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
247188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
247288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
247388ebb749SStefano Zampini     } else {
247488ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
247588ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
247688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
247788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
247888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
247988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
248088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
248188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
248288ebb749SStefano Zampini     }
248388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
248488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
248588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2486511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
24874f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2488fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
2489d12edf2fSStefano Zampini       PetscScalar *data,*data2;
24904f1b2e48SStefano Zampini       PetscInt    j;
2491d12edf2fSStefano Zampini 
24924f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2493fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
2494d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
249586c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2496d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2497d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
24984f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
24994f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2500d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
25014f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
25024f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
25034f1b2e48SStefano Zampini         }
2504d12edf2fSStefano Zampini       }
2505d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2506d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2507d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2508d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2509d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2510d12edf2fSStefano Zampini     }
2511d12edf2fSStefano Zampini #if 0
2512d12edf2fSStefano Zampini   {
2513d12edf2fSStefano Zampini     PetscViewer viewer;
2514d12edf2fSStefano Zampini     char filename[256];
2515ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2516d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2517d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2518ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2519ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2520ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2521d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
252272b8c272SStefano Zampini     if (save_change) {
252372b8c272SStefano Zampini       Mat phi_B;
252472b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
252572b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
252672b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
252772b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
252872b8c272SStefano Zampini     } else {
2529ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2530ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
253172b8c272SStefano Zampini     }
2532ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2533ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2534ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2535ffd830a3SStefano Zampini     }
2536ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2537ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2538ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2539ffd830a3SStefano Zampini     }
254072b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
2541ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2542ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2543ffd830a3SStefano Zampini     }
2544d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2545d12edf2fSStefano Zampini   }
2546d12edf2fSStefano Zampini #endif
254781d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
25488bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
25491575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
255006656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
25518bec7fa6SStefano Zampini 
25528bec7fa6SStefano Zampini     /* check constraints */
2553a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2554a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
25554f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
25568bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2557a00504b5SStefano Zampini     } else {
2558a00504b5SStefano Zampini       PetscScalar *data;
2559a00504b5SStefano Zampini       Mat         tmat;
2560a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2561a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
2562a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2563a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2564a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2565a00504b5SStefano Zampini     }
25668bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
25678bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
25688bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
25698bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2570bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2571ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
2572bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2573bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2574bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2575bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2576bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
257788ebb749SStefano Zampini     }
25788bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
25798bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
25808bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
25818bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
258225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
258388ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
258488ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
258588ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
258688ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
258788ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
258888ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
258988ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
259088ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
259188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
259288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2593ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
259488ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
259588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
259688ebb749SStefano Zampini     }
259788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
259888ebb749SStefano Zampini   }
25998629588bSStefano Zampini   /* get back data */
26008629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
260188ebb749SStefano Zampini   PetscFunctionReturn(0);
260288ebb749SStefano Zampini }
260388ebb749SStefano Zampini 
260488ebb749SStefano Zampini #undef __FUNCT__
2605d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2606d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2607aa0d41d4SStefano Zampini {
2608d65f70fdSStefano Zampini   Mat            *work_mat;
2609d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2610d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2611c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
2612aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2613aa0d41d4SStefano Zampini 
2614aa0d41d4SStefano Zampini   PetscFunctionBegin;
2615d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2616d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2617d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2618d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2619aa0d41d4SStefano Zampini 
2620d65f70fdSStefano Zampini   if (!rsorted) {
2621906d46d4SStefano Zampini     const PetscInt *idxs;
2622906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2623aa0d41d4SStefano Zampini 
2624d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2625d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2626d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2627d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2628aa0d41d4SStefano Zampini     }
2629d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2630d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2631d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2632d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2633aa0d41d4SStefano Zampini     }
2634d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2635d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2636d65f70fdSStefano Zampini   } else {
2637d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2638d65f70fdSStefano Zampini     isrow_s = isrow;
2639aa0d41d4SStefano Zampini   }
2640906d46d4SStefano Zampini 
2641d65f70fdSStefano Zampini   if (!csorted) {
2642d65f70fdSStefano Zampini     if (isrow == iscol) {
2643d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2644d65f70fdSStefano Zampini       iscol_s = isrow_s;
2645d65f70fdSStefano Zampini     } else {
2646d65f70fdSStefano Zampini       const PetscInt *idxs;
2647d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
2648906d46d4SStefano Zampini 
2649d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2650d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2651d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2652d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2653d65f70fdSStefano Zampini       }
2654d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2655d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2656d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2657d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2658d65f70fdSStefano Zampini       }
2659d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2660d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2661d65f70fdSStefano Zampini     }
2662d65f70fdSStefano Zampini   } else {
2663d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2664d65f70fdSStefano Zampini     iscol_s = iscol;
2665d65f70fdSStefano Zampini   }
2666d65f70fdSStefano Zampini 
2667d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2668d65f70fdSStefano Zampini 
2669d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2670906d46d4SStefano Zampini     Mat      new_mat;
2671d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2672906d46d4SStefano Zampini 
2673d65f70fdSStefano Zampini     if (!rsorted) {
2674d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2675d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2676d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2677d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2678906d46d4SStefano Zampini       }
2679d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2680d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2681d65f70fdSStefano Zampini     } else {
2682d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2683906d46d4SStefano Zampini     }
2684d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2685d65f70fdSStefano Zampini 
2686d65f70fdSStefano Zampini     if (!csorted) {
2687d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2688d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2689d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2690d65f70fdSStefano Zampini       } else {
2691d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2692d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2693d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2694d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2695d65f70fdSStefano Zampini         }
2696d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2697d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2698d65f70fdSStefano Zampini       }
2699d65f70fdSStefano Zampini     } else {
2700d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2701d65f70fdSStefano Zampini     }
2702d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2703d65f70fdSStefano Zampini 
2704d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2705d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2706d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2707d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2708d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2709d65f70fdSStefano Zampini   }
2710d65f70fdSStefano Zampini 
2711d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2712d65f70fdSStefano Zampini   *B = work_mat[0];
2713d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2714d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2715d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2716d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2717d65f70fdSStefano Zampini }
2718d65f70fdSStefano Zampini 
2719d65f70fdSStefano Zampini #undef __FUNCT__
27205e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
27215e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2722aa0d41d4SStefano Zampini {
2723aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
27245e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2725d65f70fdSStefano Zampini   Mat            new_mat;
27265e8657edSStefano Zampini   IS             is_local,is_global;
2727d65f70fdSStefano Zampini   PetscInt       local_size;
2728d65f70fdSStefano Zampini   PetscBool      isseqaij;
2729aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2730aa0d41d4SStefano Zampini 
2731aa0d41d4SStefano Zampini   PetscFunctionBegin;
2732aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
27335e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
27345e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2735b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2736aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2737d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2738aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2739906d46d4SStefano Zampini 
2740906d46d4SStefano Zampini   /* check */
2741906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2742906d46d4SStefano Zampini     Vec       x,x_change;
2743906d46d4SStefano Zampini     PetscReal error;
2744906d46d4SStefano Zampini 
27455e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2746906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
27475e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2748e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2749e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2750d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2751e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2752e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2753906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2754906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2755906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2756906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2757906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2758906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2759906d46d4SStefano Zampini   }
2760906d46d4SStefano Zampini 
276122d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
27629b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
276322d5777bSStefano Zampini   if (isseqaij) {
2764a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2765a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2766aa0d41d4SStefano Zampini   } else {
2767a00504b5SStefano Zampini     Mat work_mat;
27681cf9b237SStefano Zampini 
2769a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2770aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2771a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2772aa0d41d4SStefano Zampini   }
27733301b35fSStefano Zampini   if (matis->A->symmetric_set) {
27743301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2775e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
27763301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2777e496cd5dSStefano Zampini #endif
27783301b35fSStefano Zampini   }
2779d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2780aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2781aa0d41d4SStefano Zampini }
2782aa0d41d4SStefano Zampini 
2783aa0d41d4SStefano Zampini #undef __FUNCT__
2784a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
27858ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2786a64d13efSStefano Zampini {
2787a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2788a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2789d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
279053892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
27913a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
27923a50541eSStefano Zampini   PetscInt        vbs,bs;
27936816873aSStefano Zampini   PetscBT         bitmask=NULL;
2794a64d13efSStefano Zampini   PetscErrorCode  ierr;
2795a64d13efSStefano Zampini 
2796a64d13efSStefano Zampini   PetscFunctionBegin;
2797b23d619eSStefano Zampini   /*
2798b23d619eSStefano Zampini     No need to setup local scatters if
2799b23d619eSStefano Zampini       - primal space is unchanged
2800b23d619eSStefano Zampini         AND
2801b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2802b23d619eSStefano Zampini         AND
2803b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2804b23d619eSStefano Zampini   */
2805b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2806f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2807f4ddd8eeSStefano Zampini   }
2808f4ddd8eeSStefano Zampini   /* destroy old objects */
2809f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2810f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2811f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2812a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2813b371cd4fSStefano Zampini   n_B = pcis->n_B;
2814b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2815b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
28163a50541eSStefano Zampini 
2817a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
28186816873aSStefano Zampini 
281953892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2820df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
2821854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2822a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2823a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
28240e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2825a64d13efSStefano Zampini     }
2826a64d13efSStefano Zampini 
2827a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
28284641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
28296816873aSStefano Zampini         idx_R_local[n_R++] = i;
2830a64d13efSStefano Zampini       }
2831a64d13efSStefano Zampini     }
2832df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2833df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
28346816873aSStefano Zampini 
2835df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2836df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
28376816873aSStefano Zampini   }
28383a50541eSStefano Zampini 
28393a50541eSStefano Zampini   /* Block code */
28403a50541eSStefano Zampini   vbs = 1;
28413a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
28423a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
28433a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
28443a50541eSStefano Zampini     PetscInt  *vary;
2845df4d28bfSStefano Zampini     if (!sub_schurs->reuse_solver) {
2846785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
28473a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2848d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2849d3df7717SStefano 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 */
28500e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2851d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
28523a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
28533a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
28543a50541eSStefano Zampini           break;
28553a50541eSStefano Zampini         }
28563a50541eSStefano Zampini       }
2857d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2858d3df7717SStefano Zampini     } else {
2859d3df7717SStefano Zampini       /* Verify directly the R set */
2860d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2861d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2862d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2863d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2864d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2865d3df7717SStefano Zampini             break;
2866d3df7717SStefano Zampini           }
2867d3df7717SStefano Zampini         }
2868d3df7717SStefano Zampini       }
2869d3df7717SStefano Zampini     }
28703a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
28713a50541eSStefano Zampini       vbs = bs;
28723a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
28733a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
28743a50541eSStefano Zampini       }
28753a50541eSStefano Zampini     }
28763a50541eSStefano Zampini   }
28773a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2878df4d28bfSStefano Zampini   if (sub_schurs->reuse_solver) {
2879df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
288053892102SStefano Zampini 
2881df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2882df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
288353892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2884df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
288553892102SStefano Zampini   } else {
28863a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
288753892102SStefano Zampini   }
2888a64d13efSStefano Zampini 
2889a64d13efSStefano Zampini   /* print some info if requested */
2890a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2891a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2892a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
28931575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2894a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2895a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
28964f1b2e48SStefano 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);
2897a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2898a64d13efSStefano Zampini   }
2899a64d13efSStefano Zampini 
2900a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
2901df4d28bfSStefano Zampini   if (!sub_schurs->reuse_solver) {
29026816873aSStefano Zampini     IS       is_aux1,is_aux2;
29036816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
29046816873aSStefano Zampini 
29053a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2906854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2907854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2908a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
29094641a718SStefano Zampini     for (i=0; i<n_D; i++) {
29104641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
29114641a718SStefano Zampini     }
2912a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2913a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
29144641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
29154641a718SStefano Zampini         aux_array1[j++] = i;
2916a64d13efSStefano Zampini       }
2917a64d13efSStefano Zampini     }
2918a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2919a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2920a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
29214641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
29224641a718SStefano Zampini         aux_array2[j++] = i;
2923a64d13efSStefano Zampini       }
2924a64d13efSStefano Zampini     }
2925a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2926a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2927a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2928a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2929a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2930a64d13efSStefano Zampini 
29318eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2932785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2933a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
29344641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
29354641a718SStefano Zampini           aux_array1[j++] = i;
2936a64d13efSStefano Zampini         }
2937a64d13efSStefano Zampini       }
2938a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2939a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2940a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2941a64d13efSStefano Zampini     }
29424641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
29433a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2944d62866d3SStefano Zampini   } else {
2945df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
29466816873aSStefano Zampini     IS                 tis;
29476816873aSStefano Zampini     PetscInt           schur_size;
29486816873aSStefano Zampini 
2949df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
29506816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
2951df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
29526816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
29536816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
29546816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
29556816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
29566816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2957d62866d3SStefano Zampini     }
2958d62866d3SStefano Zampini   }
2959a64d13efSStefano Zampini   PetscFunctionReturn(0);
2960a64d13efSStefano Zampini }
2961a64d13efSStefano Zampini 
2962304d26faSStefano Zampini 
2963304d26faSStefano Zampini #undef __FUNCT__
2964304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2965684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2966304d26faSStefano Zampini {
2967304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2968304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2969304d26faSStefano Zampini   PC             pc_temp;
2970304d26faSStefano Zampini   Mat            A_RR;
2971f4ddd8eeSStefano Zampini   MatReuse       reuse;
2972304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2973304d26faSStefano Zampini   PetscReal      value;
297404708bb6SStefano Zampini   PetscInt       n_D,n_R;
29759577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
2976304d26faSStefano Zampini   PetscErrorCode ierr;
2977e604994aSStefano Zampini   /* prefixes stuff */
2978312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2979e604994aSStefano Zampini   size_t         len;
2980304d26faSStefano Zampini 
2981304d26faSStefano Zampini   PetscFunctionBegin;
2982304d26faSStefano Zampini 
2983e604994aSStefano Zampini   /* compute prefixes */
2984e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2985e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2986e604994aSStefano Zampini   if (!pcbddc->current_level) {
2987e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2988e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2989e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2990e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2991e604994aSStefano Zampini   } else {
2992e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2993312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2994e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2995e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2996312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2997312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
299834d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
299934d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3000e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3001e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3002e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
3003e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
3004e604994aSStefano Zampini   }
3005e604994aSStefano Zampini 
3006304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
3007684f6988SStefano Zampini   if (dirichlet) {
3008d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3009450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3010450f8f5eSStefano Zampini       if (!sub_schurs->reuse_solver) {
3011450f8f5eSStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
3012450f8f5eSStefano Zampini       }
3013450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
3014a3df083aSStefano Zampini         Mat    A_IIn;
3015a3df083aSStefano Zampini 
3016a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
3017a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
3018a3df083aSStefano Zampini         pcis->A_II = A_IIn;
3019a3df083aSStefano Zampini       }
3020450f8f5eSStefano Zampini     }
30213301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
30223301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
3023964fefecSStefano Zampini     }
3024ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
3025964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
3026304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
3027304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
3028304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
3029304d26faSStefano Zampini       /* default */
3030304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3031e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
30329577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3033304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
30349577ea80SStefano Zampini       if (issbaij) {
30359577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
30369577ea80SStefano Zampini       } else {
3037304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
30389577ea80SStefano Zampini       }
3039304d26faSStefano Zampini       /* Allow user's customization */
3040304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3041304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3042304d26faSStefano Zampini     }
3043d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
3044df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
3045df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3046d62866d3SStefano Zampini 
3047df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
3048d5574798SStefano Zampini     }
3049304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3050304d26faSStefano Zampini     if (!n_D) {
3051304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
3052304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3053304d26faSStefano Zampini     }
3054304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
3055304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
3056304d26faSStefano Zampini     /* set ksp_D into pcis data */
3057304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
3058304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
3059304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
3060684f6988SStefano Zampini   }
3061304d26faSStefano Zampini 
3062304d26faSStefano Zampini   /* NEUMANN PROBLEM */
3063684f6988SStefano Zampini   A_RR = 0;
3064684f6988SStefano Zampini   if (neumann) {
3065d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
306604708bb6SStefano Zampini     PetscInt        ibs,mbs;
306704708bb6SStefano Zampini     PetscBool       issbaij;
306804708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
3069f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
30708ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
3071f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
3072f4ddd8eeSStefano Zampini       PetscInt nn_R;
307381d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
3074f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3075f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
3076f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
3077f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
3078f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3079f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3080f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
3081727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
3082f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3083f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
3084f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
3085f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
3086f4ddd8eeSStefano Zampini         }
3087f4ddd8eeSStefano Zampini       }
3088f4ddd8eeSStefano Zampini       /* last check */
3089d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
3090f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3091f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3092f4ddd8eeSStefano Zampini       }
3093f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
3094f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
3095f4ddd8eeSStefano Zampini     }
3096a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
3097af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3098af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
309904708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
310004708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
310104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
310204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
310304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
3104af732b37SStefano Zampini       } else {
3105511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
31066816873aSStefano Zampini       }
310704708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
310804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
310904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
311004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
311104708bb6SStefano Zampini       } else {
3112511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
311304708bb6SStefano Zampini       }
311404708bb6SStefano Zampini     }
3115a00504b5SStefano Zampini     /* extract A_RR */
3116a00504b5SStefano Zampini     if (sub_schurs->reuse_solver) {
3117a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3118a00504b5SStefano Zampini 
3119a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
312016e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3121a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
312216e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
312316e386b8SStefano Zampini         } else {
3124a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
3125a00504b5SStefano Zampini         }
3126a00504b5SStefano Zampini       } else {
3127a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3128a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
3129a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3130a00504b5SStefano Zampini       }
3131a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
3132f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
313316e386b8SStefano Zampini     }
31343301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
31353301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
31366816873aSStefano Zampini     }
3137f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
3138304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
3139304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
3140304d26faSStefano Zampini       /* default */
3141304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3142e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
3143304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
31449577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
31459577ea80SStefano Zampini       if (issbaij) {
31469577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
31479577ea80SStefano Zampini       } else {
3148304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
31499577ea80SStefano Zampini       }
3150304d26faSStefano Zampini       /* Allow user's customization */
3151304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3152304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3153304d26faSStefano Zampini     }
3154304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3155304d26faSStefano Zampini     if (!n_R) {
3156304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
3157304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3158304d26faSStefano Zampini     }
31595cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
3160df4d28bfSStefano Zampini     /* Reuse solver if it is present */
3161df4d28bfSStefano Zampini     if (sub_schurs->reuse_solver) {
3162df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3163d62866d3SStefano Zampini 
3164df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
3165d62866d3SStefano Zampini     }
3166304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
3167304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
3168684f6988SStefano Zampini   }
3169304d26faSStefano Zampini 
3170304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
31710fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
3172684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
3173684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
31741575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3175684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3176684f6988SStefano Zampini     }
3177684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
31780fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
31790fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
31800fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
31810fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
31820fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
3183304d26faSStefano Zampini       /* need to be adapted? */
3184b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
3185b2566f29SBarry Smith       ierr = MPIU_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3186b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
3187304d26faSStefano Zampini       /* print info */
3188304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
3189e604994aSStefano 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);
3190304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3191304d26faSStefano Zampini       }
3192b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
3193298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
3194304d26faSStefano Zampini       }
3195684f6988SStefano Zampini     }
3196684f6988SStefano Zampini     if (neumann) { /* Neumann */
31970fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
31980fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
31990fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
32000fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
32010fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
3202304d26faSStefano Zampini       /* need to be adapted? */
3203b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
3204b2566f29SBarry Smith       ierr = MPIU_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3205304d26faSStefano Zampini       /* print info */
3206304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
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);
3208304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3209304d26faSStefano Zampini       }
3210b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
3211298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
3212304d26faSStefano Zampini       }
32130fccc4e9SStefano Zampini     }
3214684f6988SStefano Zampini   }
32155cbda25cSStefano Zampini   /* free Neumann problem's matrix */
32165cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3217304d26faSStefano Zampini   PetscFunctionReturn(0);
3218304d26faSStefano Zampini }
3219304d26faSStefano Zampini 
3220304d26faSStefano Zampini #undef __FUNCT__
3221ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
322280677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
3223674ae819SStefano Zampini {
3224674ae819SStefano Zampini   PetscErrorCode  ierr;
3225674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3226be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3227674ae819SStefano Zampini 
3228674ae819SStefano Zampini   PetscFunctionBegin;
3229df4d28bfSStefano Zampini   if (!sub_schurs->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     }
3237df4d28bfSStefano Zampini     if (!sub_schurs->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   }
325872b8c272SStefano Zampini   if (!sub_schurs->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) {
3275df4d28bfSStefano Zampini     if (!sub_schurs->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   /* TODO remove null space when doing multilevel */
334612edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
334751694757SStefano Zampini     Mat          coarse_mat;
3348964fefecSStefano Zampini     Vec          rhs,sol;
334951694757SStefano Zampini     MatNullSpace nullsp;
335027b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
3351964fefecSStefano Zampini 
335227b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
335327b6a85dSStefano Zampini       PC        coarse_pc;
335427b6a85dSStefano Zampini 
335527b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
335627b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
335727b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
335827b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
335927b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
336027b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
33613bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
336227b6a85dSStefano Zampini       }
336327b6a85dSStefano Zampini     }
3364964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3365964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
336651694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
336751694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
336851694757SStefano Zampini     if (nullsp) {
336951694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
337051694757SStefano Zampini     }
337112edc857SStefano Zampini     if (applytranspose) {
33721f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only) {
33731f4df5f7SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
33742701bc32SStefano Zampini       } else {
3375964fefecSStefano Zampini         ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
33762701bc32SStefano Zampini       }
33772701bc32SStefano Zampini     } else {
33781f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
33792701bc32SStefano Zampini         PC        coarse_pc;
33802701bc32SStefano Zampini 
33812701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
33822701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
3383*3e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
33842701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
338512edc857SStefano Zampini       } else {
3386964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
338712edc857SStefano Zampini       }
33882701bc32SStefano Zampini     }
338927b6a85dSStefano Zampini     /* we don't the benign correction at coarser levels anymore */
339027b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
339127b6a85dSStefano Zampini       PC        coarse_pc;
339227b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
339327b6a85dSStefano Zampini 
339427b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
339527b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
339627b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
33973bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
339827b6a85dSStefano Zampini     }
339951694757SStefano Zampini     if (nullsp) {
340051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
340151694757SStefano Zampini     }
340212edc857SStefano Zampini   }
3403674ae819SStefano Zampini 
3404674ae819SStefano Zampini   /* Local solution on R nodes */
34054fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
340680677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
34079f00e9b4SStefano Zampini   }
34089f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
34099f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
341012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3411674ae819SStefano Zampini 
34124fee134fSStefano Zampini   /* Sum contributions from the two levels */
34134fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3414dc359a40SStefano Zampini     if (applytranspose) {
3415dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3416dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3417dc359a40SStefano Zampini     } else {
3418674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
34198eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3420dc359a40SStefano Zampini     }
3421efc2fbd9SStefano Zampini     /* store p0 */
34224f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3423efc2fbd9SStefano Zampini       PetscScalar *array;
34244f1b2e48SStefano Zampini       PetscInt    j;
3425efc2fbd9SStefano Zampini 
3426efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
34274f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3428efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3429efc2fbd9SStefano Zampini     }
34304fee134fSStefano Zampini   } else { /* expand the coarse solution */
34314fee134fSStefano Zampini     if (applytranspose) {
34324fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
34334fee134fSStefano Zampini     } else {
34344fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
34354fee134fSStefano Zampini     }
34364fee134fSStefano Zampini   }
3437674ae819SStefano Zampini   PetscFunctionReturn(0);
3438674ae819SStefano Zampini }
3439674ae819SStefano Zampini 
3440674ae819SStefano Zampini #undef __FUNCT__
3441674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
344212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3443674ae819SStefano Zampini {
3444674ae819SStefano Zampini   PetscErrorCode ierr;
3445674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
344658da7f69SStefano Zampini   PetscScalar    *array;
344712edc857SStefano Zampini   Vec            from,to;
3448674ae819SStefano Zampini 
3449674ae819SStefano Zampini   PetscFunctionBegin;
345012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
345112edc857SStefano Zampini     from = pcbddc->coarse_vec;
345212edc857SStefano Zampini     to = pcbddc->vec1_P;
345312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
345412edc857SStefano Zampini       Vec tvec;
345558da7f69SStefano Zampini 
345658da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
345758da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
345812edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
345958da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
346058da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
346158da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
346212edc857SStefano Zampini     }
346312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
346412edc857SStefano Zampini     from = pcbddc->vec1_P;
346512edc857SStefano Zampini     to = pcbddc->coarse_vec;
346612edc857SStefano Zampini   }
346712edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3468674ae819SStefano Zampini   PetscFunctionReturn(0);
3469674ae819SStefano Zampini }
3470674ae819SStefano Zampini 
3471674ae819SStefano Zampini #undef __FUNCT__
3472674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
347312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3474674ae819SStefano Zampini {
3475674ae819SStefano Zampini   PetscErrorCode ierr;
3476674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
347758da7f69SStefano Zampini   PetscScalar    *array;
347812edc857SStefano Zampini   Vec            from,to;
3479674ae819SStefano Zampini 
3480674ae819SStefano Zampini   PetscFunctionBegin;
348112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
348212edc857SStefano Zampini     from = pcbddc->coarse_vec;
348312edc857SStefano Zampini     to = pcbddc->vec1_P;
348412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
348512edc857SStefano Zampini     from = pcbddc->vec1_P;
348612edc857SStefano Zampini     to = pcbddc->coarse_vec;
348712edc857SStefano Zampini   }
348812edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
348912edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
349012edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
349112edc857SStefano Zampini       Vec tvec;
349258da7f69SStefano Zampini 
349312edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
349458da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
349558da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
349658da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
349758da7f69SStefano Zampini     }
349858da7f69SStefano Zampini   } else {
349958da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
350058da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
350112edc857SStefano Zampini     }
350212edc857SStefano Zampini   }
3503674ae819SStefano Zampini   PetscFunctionReturn(0);
3504674ae819SStefano Zampini }
3505674ae819SStefano Zampini 
3506984c4197SStefano Zampini /* uncomment for testing purposes */
3507984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3508674ae819SStefano Zampini #undef __FUNCT__
3509674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3510674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3511674ae819SStefano Zampini {
3512674ae819SStefano Zampini   PetscErrorCode    ierr;
3513674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3514674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3515674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3516984c4197SStefano Zampini   /* one and zero */
3517984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3518984c4197SStefano Zampini   /* space to store constraints and their local indices */
35199162d606SStefano Zampini   PetscScalar       *constraints_data;
35209162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
35219162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
35229162d606SStefano Zampini   PetscInt          *constraints_n;
3523984c4197SStefano Zampini   /* iterators */
3524b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3525984c4197SStefano Zampini   /* BLAS integers */
3526e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3527e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3528c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3529727cdba6SStefano Zampini   /* reuse */
35300e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
35310e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3532984c4197SStefano Zampini   /* change of basis */
3533b3d85658SStefano Zampini   PetscBool         qr_needed;
35349162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3535984c4197SStefano Zampini   /* auxiliary stuff */
353664efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
35378a0068c3SStefano Zampini   PetscInt          ncc;
3538984c4197SStefano Zampini   /* some quantities */
353945a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3540a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3541984c4197SStefano Zampini 
3542674ae819SStefano Zampini   PetscFunctionBegin;
35438e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
35448e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
35458e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
354616909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
3547088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3548088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
35490e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
35500e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
35510e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
35520e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
35530e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3554088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3555cf5a6209SStefano Zampini 
3556cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
35579162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3558cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3559cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3560cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3561cf5a6209SStefano Zampini     PetscScalar  *array;
3562cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3563cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3564674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3565b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3566674ae819SStefano Zampini     PetscScalar  *work;
3567674ae819SStefano Zampini     PetscReal    *singular_vals;
3568674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3569674ae819SStefano Zampini     PetscReal    *rwork;
3570674ae819SStefano Zampini #endif
3571674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3572674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3573674ae819SStefano Zampini #else
3574964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3575964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3576674ae819SStefano Zampini #endif
3577674ae819SStefano Zampini 
3578674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3579d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3580e4d548c7SStefano Zampini     /* print some info */
35811f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
3582e4d548c7SStefano Zampini       PetscInt nv;
3583e4d548c7SStefano Zampini 
3584e4d548c7SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
3585e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
3586e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3587e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3588e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3589e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
3590e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
3591e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3592e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3593e4d548c7SStefano Zampini     }
3594e4d548c7SStefano Zampini 
3595d06fc5fdSStefano Zampini     /* free unneeded index sets */
3596d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3597d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3598674ae819SStefano Zampini     }
3599d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3600d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3601d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3602d06fc5fdSStefano Zampini       }
3603d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3604d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3605d06fc5fdSStefano Zampini     }
3606d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3607d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3608d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3609d06fc5fdSStefano Zampini       }
3610d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3611d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3612d06fc5fdSStefano Zampini     }
361370022509SStefano Zampini 
361470022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
361570022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
361670022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
361770022509SStefano Zampini     if (pcbddc->NullSpace) {
361870022509SStefano Zampini       PetscBool tbool[2],gbool[2];
361970022509SStefano Zampini 
362070022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
3621b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
3622d06fc5fdSStefano Zampini         if (!ISForEdges) {
3623d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
3624d06fc5fdSStefano Zampini         }
3625b8ffe317SStefano Zampini       }
3626d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
3627d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
3628b2566f29SBarry Smith       ierr = MPIU_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3629d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
3630d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
363198a51de6SStefano Zampini     }
363270022509SStefano Zampini #endif
363308122e43SStefano Zampini 
3634674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3635674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3636674ae819SStefano Zampini     if (nearnullsp) {
3637674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3638f4ddd8eeSStefano Zampini       /* remove any stored info */
3639f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3640f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3641f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3642f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3643f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3644473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3645f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3646f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3647f4ddd8eeSStefano Zampini       }
3648984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3649984c4197SStefano Zampini       nnsp_size = 0;
3650674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3651674ae819SStefano Zampini     }
3652984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3653984c4197SStefano Zampini     max_constraints = nnsp_size;
3654984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3655984c4197SStefano Zampini 
3656674ae819SStefano Zampini     /*
3657674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
36589162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
36599162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
36609162d606SStefano Zampini          There can be multiple constraints per connected component
3661674ae819SStefano Zampini                                                                                                                                                            */
3662674ae819SStefano Zampini     n_vertices = 0;
3663674ae819SStefano Zampini     if (ISForVertices) {
3664674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3665674ae819SStefano Zampini     }
36669162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
36679162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
36689162d606SStefano Zampini 
36699162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
36709162d606SStefano Zampini     total_counts *= max_constraints;
3671674ae819SStefano Zampini     total_counts += n_vertices;
36724641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
36739162d606SStefano Zampini 
3674674ae819SStefano Zampini     total_counts = 0;
3675674ae819SStefano Zampini     max_size_of_constraint = 0;
3676674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
36779162d606SStefano Zampini       IS used_is;
3678674ae819SStefano Zampini       if (i<n_ISForEdges) {
36799162d606SStefano Zampini         used_is = ISForEdges[i];
3680674ae819SStefano Zampini       } else {
36819162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3682674ae819SStefano Zampini       }
36839162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3684674ae819SStefano Zampini       total_counts += j;
3685674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3686674ae819SStefano Zampini     }
36879162d606SStefano 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);
36889162d606SStefano Zampini 
3689984c4197SStefano Zampini     /* get local part of global near null space vectors */
3690785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3691984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3692984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3693e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3694e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3695984c4197SStefano Zampini     }
3696674ae819SStefano Zampini 
3697242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3698242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3699a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3700242a89d7SStefano Zampini 
3701984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3702a773dcb8SStefano Zampini     if (!skip_lapack) {
3703674ae819SStefano Zampini       PetscScalar temp_work;
3704911cabfeSStefano Zampini 
3705674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3706984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3707785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3708785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3709785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3710674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3711785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3712674ae819SStefano Zampini #endif
3713674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3714c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3715c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3716674ae819SStefano Zampini       lwork = -1;
3717674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3718674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3719c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3720674ae819SStefano Zampini #else
3721c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3722674ae819SStefano Zampini #endif
3723674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3724984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3725674ae819SStefano Zampini #else /* on missing GESVD */
3726674ae819SStefano Zampini       /* SVD */
3727674ae819SStefano Zampini       PetscInt max_n,min_n;
3728674ae819SStefano Zampini       max_n = max_size_of_constraint;
3729984c4197SStefano Zampini       min_n = max_constraints;
3730984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3731674ae819SStefano Zampini         min_n = max_size_of_constraint;
3732984c4197SStefano Zampini         max_n = max_constraints;
3733674ae819SStefano Zampini       }
3734785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3735674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3736785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3737674ae819SStefano Zampini #endif
3738674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3739674ae819SStefano Zampini       lwork = -1;
3740e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3741e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3742b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3743674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3744674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
37459162d606SStefano 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));
3746674ae819SStefano Zampini #else
37479162d606SStefano 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));
3748674ae819SStefano Zampini #endif
3749674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3750984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3751984c4197SStefano Zampini #endif /* on missing GESVD */
3752674ae819SStefano Zampini       /* Allocate optimal workspace */
3753674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3754854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3755674ae819SStefano Zampini     }
3756674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3757674ae819SStefano Zampini     total_counts = 0;
37589162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
37599162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3760674ae819SStefano Zampini     /* vertices */
37619162d606SStefano Zampini     if (n_vertices) {
3762674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
37639162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3764674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
37659162d606SStefano Zampini         constraints_n[total_counts] = 1;
37669162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
37679162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
37689162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3769674ae819SStefano Zampini         total_counts++;
3770674ae819SStefano Zampini       }
3771674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3772674ae819SStefano Zampini       n_vertices = total_counts;
3773674ae819SStefano Zampini     }
3774984c4197SStefano Zampini 
3775674ae819SStefano Zampini     /* edges and faces */
37769162d606SStefano Zampini     total_counts_cc = total_counts;
3777911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
37789162d606SStefano Zampini       IS        used_is;
37799162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
37809162d606SStefano Zampini 
3781911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
37829162d606SStefano Zampini         used_is = ISForEdges[ncc];
3783984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3784674ae819SStefano Zampini       } else {
37859162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3786984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3787674ae819SStefano Zampini       }
3788674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
37899162d606SStefano Zampini 
37909162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
37919162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3792984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3793984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3794674ae819SStefano Zampini       if (nnsp_has_cnst) {
37955b08dc53SStefano Zampini         PetscScalar quad_value;
37969162d606SStefano Zampini 
37979162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
37989162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
37999162d606SStefano Zampini 
3800a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3801674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3802a773dcb8SStefano Zampini         } else {
3803a773dcb8SStefano Zampini           quad_value = 1.0;
3804a773dcb8SStefano Zampini         }
3805674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
38069162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3807674ae819SStefano Zampini         }
38089162d606SStefano Zampini         temp_constraints++;
3809674ae819SStefano Zampini         total_counts++;
3810674ae819SStefano Zampini       }
3811674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3812984c4197SStefano Zampini         PetscReal real_value;
38139162d606SStefano Zampini         PetscScalar *ptr_to_data;
38149162d606SStefano Zampini 
3815984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
38169162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3817674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
38189162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3819674ae819SStefano Zampini         }
3820984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3821984c4197SStefano Zampini         /* check if array is null on the connected component */
3822e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
38239162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
38245b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3825674ae819SStefano Zampini           temp_constraints++;
3826674ae819SStefano Zampini           total_counts++;
38279162d606SStefano Zampini           if (!idxs_copied) {
38289162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
38299162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3830674ae819SStefano Zampini           }
3831674ae819SStefano Zampini         }
38329162d606SStefano Zampini       }
38339162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
383445a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3835eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3836a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
38379162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
38389162d606SStefano Zampini 
38399162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3840a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
38419162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3842a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
38439162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3844a773dcb8SStefano Zampini         } else { /* perform SVD */
3845984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
38469162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3847674ae819SStefano Zampini 
3848674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3849984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3850984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3851984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3852984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3853984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3854984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3855984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3856984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3857674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3858e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3859984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3860674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3861674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
38629162d606SStefano 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));
3863674ae819SStefano Zampini             }
3864674ae819SStefano Zampini           }
3865e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3866e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3867e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3868674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3869c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3870674ae819SStefano Zampini #else
3871c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3872674ae819SStefano Zampini #endif
3873674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3874984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3875984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3876674ae819SStefano Zampini           j = 0;
3877984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3878674ae819SStefano Zampini           total_counts = total_counts-j;
387945a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3880e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3881c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3882c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3883c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3884c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3885c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3886c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3887674ae819SStefano Zampini           if (j<temp_constraints) {
3888984c4197SStefano Zampini             PetscInt ii;
3889984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3890674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
38919162d606SStefano 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));
3892674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3893984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3894674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
38959162d606SStefano 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];
3896674ae819SStefano Zampini               }
3897674ae819SStefano Zampini             }
3898674ae819SStefano Zampini           }
3899674ae819SStefano Zampini #else  /* on missing GESVD */
3900e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3901e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3902b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3903674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3904674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
39059162d606SStefano 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));
3906674ae819SStefano Zampini #else
39079162d606SStefano 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));
3908674ae819SStefano Zampini #endif
3909984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3910674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3911984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3912e310c8b4SStefano Zampini           k = temp_constraints;
3913e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3914674ae819SStefano Zampini           j = 0;
3915e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
391645a1bb75SStefano Zampini           valid_constraints = k-j;
3917911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3918984c4197SStefano Zampini #endif /* on missing GESVD */
3919674ae819SStefano Zampini         }
3920a773dcb8SStefano Zampini       }
39219162d606SStefano Zampini       /* update pointers information */
39229162d606SStefano Zampini       if (valid_constraints) {
39239162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
39249162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
39259162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
39269162d606SStefano Zampini         /* set change_of_basis flag */
392745a1bb75SStefano Zampini         if (boolforchange) {
3928b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
39299162d606SStefano Zampini         }
3930b3d85658SStefano Zampini         total_counts_cc++;
393145a1bb75SStefano Zampini       }
393245a1bb75SStefano Zampini     }
3933984c4197SStefano Zampini     /* free workspace */
39348f1c130eSStefano Zampini     if (!skip_lapack) {
3935984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3936984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3937984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3938984c4197SStefano Zampini #endif
3939984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3940984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3941984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3942984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3943984c4197SStefano Zampini #endif
3944984c4197SStefano Zampini     }
3945984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3946984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3947984c4197SStefano Zampini     }
3948984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3949cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3950cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3951cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3952cf5a6209SStefano Zampini     }
3953cf5a6209SStefano Zampini     if (n_ISForFaces) {
3954cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3955cf5a6209SStefano Zampini     }
3956cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3957cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3958cf5a6209SStefano Zampini     }
3959cf5a6209SStefano Zampini     if (n_ISForEdges) {
3960cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3961cf5a6209SStefano Zampini     }
3962cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
396308122e43SStefano Zampini   } else {
396408122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3965984c4197SStefano Zampini 
396608122e43SStefano Zampini     total_counts = 0;
396708122e43SStefano Zampini     n_vertices = 0;
3968d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3969d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
397008122e43SStefano Zampini     }
397108122e43SStefano Zampini     max_constraints = 0;
39729162d606SStefano Zampini     total_counts_cc = 0;
397308122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
397408122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
39759162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
397608122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
397708122e43SStefano Zampini     }
39789162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
39799162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
39809162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
39819162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
398274d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
39839162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
39849162d606SStefano Zampini     total_counts_cc = 0;
39859162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
39869162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
39879162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
398808122e43SStefano Zampini       }
398908122e43SStefano Zampini     }
39909162d606SStefano Zampini #if 0
39919162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
39929162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
39939162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
39949162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
39959162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
39969162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
39979162d606SStefano Zampini       }
39989162d606SStefano Zampini       printf("\n");
39999162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
40009162d606SStefano Zampini     }
40011b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
40028bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
40031b968477SStefano Zampini     }
40041b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
40058bec7fa6SStefano 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]);
40061b968477SStefano Zampini     }
400708122e43SStefano Zampini #endif
400808122e43SStefano Zampini 
40098bec7fa6SStefano Zampini     max_size_of_constraint = 0;
40109162d606SStefano 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]);
40119162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
401208122e43SStefano Zampini     /* Change of basis */
4013b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
401408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
401508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
401608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
4017b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
401808122e43SStefano Zampini         }
401908122e43SStefano Zampini       }
402008122e43SStefano Zampini     }
402108122e43SStefano Zampini   }
4022984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
40234f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
402408122e43SStefano Zampini 
40259162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
40269162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
40276c4ed002SBarry 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);
4028674ae819SStefano Zampini 
4029674ae819SStefano Zampini   /* Create constraint matrix */
4030674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
403116f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
4032984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
4033984c4197SStefano Zampini 
4034984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
4035a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
4036a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
403774d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
4038984c4197SStefano Zampini   total_primal_vertices=0;
4039b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
40409162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
40419162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
404272b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
40439162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
4044b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
404564efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
40469162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
40479162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
4048a717540cSStefano Zampini       }
4049b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
405091af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
4051a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
4052a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
4053a717540cSStefano Zampini       }
4054fa434743SStefano Zampini     } else {
4055b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
4056fa434743SStefano Zampini     }
4057a717540cSStefano Zampini   }
4058b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
4059b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
4060674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
406170022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4062b3d85658SStefano Zampini 
40634f1b2e48SStefano 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);
40640e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
40650e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
4066984c4197SStefano Zampini 
4067984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
406874d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
4069785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
4070984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
407174d5cdf7SStefano Zampini 
4072984c4197SStefano Zampini   j = total_primal_vertices;
407374d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
4074b3d85658SStefano Zampini   cum = total_primal_vertices;
40759162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
40764641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
4077b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
4078b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
4079b3d85658SStefano Zampini       cum++;
40809162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
408174d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
408274d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
408374d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
408474d5cdf7SStefano Zampini       }
40859162d606SStefano Zampini       j += constraints_n[i];
4086674ae819SStefano Zampini     }
4087674ae819SStefano Zampini   }
4088674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
4089674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
4090088faed8SStefano Zampini 
4091674ae819SStefano Zampini   /* set values in constraint matrix */
4092984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
40930e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4094674ae819SStefano Zampini   }
4095984c4197SStefano Zampini   total_counts = total_primal_vertices;
40969162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
40974641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
40989162d606SStefano Zampini       PetscInt *cols;
40999162d606SStefano Zampini 
41009162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
41019162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
41029162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
41039162d606SStefano Zampini         PetscInt    row = total_counts+k;
41049162d606SStefano Zampini         PetscScalar *vals;
41059162d606SStefano Zampini 
41069162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
41079162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
41089162d606SStefano Zampini       }
41099162d606SStefano Zampini       total_counts += constraints_n[i];
4110674ae819SStefano Zampini     }
4111674ae819SStefano Zampini   }
4112674ae819SStefano Zampini   /* assembling */
4113674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4114674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4115088faed8SStefano Zampini 
4116984c4197SStefano Zampini   /*
41176a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4118984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
4119f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
4120984c4197SStefano Zampini   */
4121674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
4122674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
4123026de310SStefano Zampini     /* dual and primal dofs on a single cc */
4124984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
4125984c4197SStefano Zampini     /* working stuff for GEQRF */
412681d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
4127984c4197SStefano Zampini     PetscBLASInt lqr_work;
4128984c4197SStefano Zampini     /* working stuff for UNGQR */
4129984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
4130984c4197SStefano Zampini     PetscBLASInt lgqr_work;
4131984c4197SStefano Zampini     /* working stuff for TRTRS */
4132984c4197SStefano Zampini     PetscScalar  *trs_rhs;
41333f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
4134984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
4135984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
4136984c4197SStefano Zampini     PetscScalar  *start_vals;
4137984c4197SStefano Zampini     /* working stuff for values insertion */
41384641a718SStefano Zampini     PetscBT      is_primal;
413964efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
4140906d46d4SStefano Zampini     /* matrix sizes */
4141906d46d4SStefano Zampini     PetscInt     global_size,local_size;
4142906d46d4SStefano Zampini     /* temporary change of basis */
4143906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
4144cf5a6209SStefano Zampini     /* extra space for debugging */
4145cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
4146984c4197SStefano Zampini 
4147906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
4148906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
414916f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
4150bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
4151906d46d4SStefano Zampini     /* nonzeros for local mat */
4152bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
41531dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4154bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
41551dd7afcfSStefano Zampini     } else {
41561dd7afcfSStefano Zampini       const PetscInt *ii;
41571dd7afcfSStefano Zampini       PetscInt       n;
41581dd7afcfSStefano Zampini       PetscBool      flg_row;
41591dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
41601dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
41611dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
41621dd7afcfSStefano Zampini     }
41639162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
4164a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
41659162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
4166a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
41679162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
4168a717540cSStefano Zampini         } else {
41699162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
41709162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
4171a717540cSStefano Zampini         }
4172a717540cSStefano Zampini       }
4173a717540cSStefano Zampini     }
4174906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
4175bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
41761dd7afcfSStefano Zampini     /* Set interior change in the matrix */
41771dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4178bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
4179906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
4180a717540cSStefano Zampini       }
41811dd7afcfSStefano Zampini     } else {
41821dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
41831dd7afcfSStefano Zampini       PetscScalar    *aa;
41841dd7afcfSStefano Zampini       PetscInt       n;
41851dd7afcfSStefano Zampini       PetscBool      flg_row;
41861dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
41871dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
41881dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
41891dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
41901dd7afcfSStefano Zampini       }
41911dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
41921dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
41931dd7afcfSStefano Zampini     }
4194a717540cSStefano Zampini 
4195a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
4196a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4197a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4198a717540cSStefano Zampini     }
4199a717540cSStefano Zampini 
4200a717540cSStefano Zampini 
4201a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
4202a717540cSStefano Zampini     /*
4203a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
4204a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
4205a717540cSStefano Zampini 
4206a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
4207a717540cSStefano Zampini 
4208a6b551f4SStefano 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)
4209a6b551f4SStefano Zampini 
4210a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
4211a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
4212a717540cSStefano Zampini             |              ...                        |
4213a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
4214a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
4215a717540cSStefano Zampini 
4216a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
4217a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
4218a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
4219a6b551f4SStefano Zampini 
4220a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
4221a717540cSStefano Zampini     */
4222a717540cSStefano Zampini     if (qr_needed) {
4223984c4197SStefano Zampini       /* space to store Q */
4224854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
4225984c4197SStefano Zampini       /* first we issue queries for optimal work */
42263f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
42273f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
42283f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4229984c4197SStefano Zampini       lqr_work = -1;
42303f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
4231984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
4232984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
4233785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
4234984c4197SStefano Zampini       lgqr_work = -1;
42353f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
42363f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
42373f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
42383f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
42393f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
42403f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
4241984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
4242984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
4243785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
4244984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
4245785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
4246984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
4247785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
4248a717540cSStefano Zampini       /* allocating workspace for check */
4249a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
4250cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
4251a717540cSStefano Zampini       }
4252a717540cSStefano Zampini     }
4253984c4197SStefano Zampini     /* array to store whether a node is primal or not */
42544641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
4255473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
42560e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
42576c4ed002SBarry 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);
425839e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
425939e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
426039e2fb2aSStefano Zampini     }
426139e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
4262984c4197SStefano Zampini 
4263a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
42649162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
42659162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
42664641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
4267984c4197SStefano Zampini         /* get constraint info */
42689162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
4269984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
4270984c4197SStefano Zampini 
4271984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
42729162d606SStefano 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);
4273674ae819SStefano Zampini         }
4274984c4197SStefano Zampini 
4275fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
4276a717540cSStefano Zampini 
4277a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
4278a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
42799162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4280a717540cSStefano Zampini           }
4281984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
42829162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4283984c4197SStefano Zampini 
4284984c4197SStefano Zampini           /* compute QR decomposition of constraints */
42853f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
42863f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42873f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4288674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
42893f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
4290984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
4291674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4292984c4197SStefano Zampini 
4293984c4197SStefano Zampini           /* explictly compute R^-T */
4294984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
4295984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
42963f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
42973f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
42983f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
42993f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
4300984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43013f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
4302984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
4303984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4304984c4197SStefano Zampini 
4305a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
43063f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
43073f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
43083f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
43093f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4310984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43113f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
4312984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
4313984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4314984c4197SStefano Zampini 
4315984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
4316984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
4317984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
43183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
43193f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
43203f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
43213f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43223f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
43233f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4324984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43259162d606SStefano 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));
4326984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
43279162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4328984c4197SStefano Zampini 
4329984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
43309162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
4331984c4197SStefano Zampini           /* insert cols for primal dofs */
4332984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
4333984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
43349162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4335906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4336984c4197SStefano Zampini           }
4337984c4197SStefano Zampini           /* insert cols for dual dofs */
4338984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
43399162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
4340984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
43419162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4342906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4343984c4197SStefano Zampini               j++;
4344674ae819SStefano Zampini             }
4345674ae819SStefano Zampini           }
4346984c4197SStefano Zampini 
4347984c4197SStefano Zampini           /* check change of basis */
4348984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
4349984c4197SStefano Zampini             PetscInt   ii,jj;
4350984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
4351c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
4352c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4353c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
4354c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4355c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
4356c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
4357984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4358cf5a6209SStefano 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));
4359984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4360984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
4361984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
4362cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
4363cf5a6209SStefano 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;
4364674ae819SStefano Zampini               }
4365674ae819SStefano Zampini             }
4366984c4197SStefano Zampini             if (!valid_qr) {
436722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
4368984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
4369984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
4370cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
4371cf5a6209SStefano 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]));
4372674ae819SStefano Zampini                   }
4373cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
4374cf5a6209SStefano 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]));
4375984c4197SStefano Zampini                   }
4376984c4197SStefano Zampini                 }
4377984c4197SStefano Zampini               }
4378674ae819SStefano Zampini             } else {
437922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
4380674ae819SStefano Zampini             }
4381674ae819SStefano Zampini           }
4382a717540cSStefano Zampini         } else { /* simple transformation block */
4383a717540cSStefano Zampini           PetscInt    row,col;
4384a6b551f4SStefano Zampini           PetscScalar val,norm;
4385a6b551f4SStefano Zampini 
4386a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
43879162d606SStefano 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));
4388a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
43899162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
43909162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4391bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
43929162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
4393906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
43949162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
4395a717540cSStefano Zampini             } else {
4396a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
43979162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4398a717540cSStefano Zampini                 if (row != col) {
43999162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
4400a717540cSStefano Zampini                 } else {
44019162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
4402a717540cSStefano Zampini                 }
4403906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
4404a717540cSStefano Zampini               }
4405a717540cSStefano Zampini             }
4406a717540cSStefano Zampini           }
440798a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
440822d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4409a717540cSStefano Zampini           }
4410674ae819SStefano Zampini         }
4411984c4197SStefano Zampini       } else {
4412984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
44139162d606SStefano 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);
4414674ae819SStefano Zampini         }
4415674ae819SStefano Zampini       }
4416674ae819SStefano Zampini     }
4417a717540cSStefano Zampini 
4418a717540cSStefano Zampini     /* free workspace */
4419a717540cSStefano Zampini     if (qr_needed) {
4420984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4421cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4422984c4197SStefano Zampini       }
4423984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4424984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4425984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4426984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4427984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4428674ae819SStefano Zampini     }
4429a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4430906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4431906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4432906d46d4SStefano Zampini 
4433906d46d4SStefano Zampini     /* assembling of global change of variable */
443488c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
4435bbb9e6c6SStefano Zampini       Mat      tmat;
443616f15bc4SStefano Zampini       PetscInt bs;
443716f15bc4SStefano Zampini 
4438906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4439906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4440bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4441bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4442bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4443bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
444416f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
444516f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4446906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4447bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4448bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4449bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4450bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4451bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4452e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4453e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4454bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4455bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
445688c03ad3SStefano Zampini 
4457906d46d4SStefano Zampini       /* check */
4458906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
4459906d46d4SStefano Zampini         PetscReal error;
4460906d46d4SStefano Zampini         Vec       x,x_change;
4461906d46d4SStefano Zampini 
4462906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4463906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4464906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4465906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4466e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4467e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4468bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4469e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4470e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4471906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4472906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4473906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4474906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4475bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4476906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
4477906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4478906d46d4SStefano Zampini       }
4479b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
4480b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
4481b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4482bf3a8328SStefano Zampini 
4483bf3a8328SStefano Zampini         if (pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined) {
4484bf3a8328SStefano Zampini           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints");CHKERRQ(ierr);
4485bf3a8328SStefano Zampini         }
4486b96c3477SStefano Zampini         if (sub_schurs->S_Ej_all) {
4487ac632422SStefano Zampini           Mat                    S_new,tmat;
4488bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
4489bbb9e6c6SStefano Zampini 
4490bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
44916816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4492bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4493bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
4494bf3a8328SStefano Zampini             IS                     is_V;
4495b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4496b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4497b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4498b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4499b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4500bf3a8328SStefano Zampini           }
4501bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4502ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4503b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4504ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4505bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4506bf3a8328SStefano Zampini             const PetscScalar *array;
4507bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
4508bf3a8328SStefano Zampini             PetscInt          i,n_V;
4509bf3a8328SStefano Zampini 
4510b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4511b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4512b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4513b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4514b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4515b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
4516b087196eSStefano Zampini               PetscScalar val;
4517b087196eSStefano Zampini               PetscInt    idx;
4518b087196eSStefano Zampini 
4519b087196eSStefano Zampini               idx = idxs_V[i];
4520b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
4521b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4522b087196eSStefano Zampini             }
4523b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4524b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4525bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4526bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4527bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4528bf3a8328SStefano Zampini           }
4529ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
4530ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4531ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
4532ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4533b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4534ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4535bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
4536b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4537bf3a8328SStefano Zampini             }
4538ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
4539ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4540ac632422SStefano Zampini           }
4541b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
454288c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4543b96c3477SStefano Zampini         }
4544c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
4545c9db6a07SStefano Zampini         if (sub_schurs->change) {
4546c9db6a07SStefano Zampini           PetscInt i;
4547c9db6a07SStefano Zampini 
4548c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
4549c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
4550c9db6a07SStefano Zampini           }
4551c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
4552c9db6a07SStefano Zampini         }
4553b96c3477SStefano Zampini       }
455416909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
455516909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
455616909a7fSStefano Zampini       } else {
4557906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
455816909a7fSStefano Zampini       }
45591dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
456027b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
456172b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
456272b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
456372b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
456472b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
456572b8c272SStefano Zampini     }
45661dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
456727b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
4568b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4569b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4570906d46d4SStefano Zampini     } else {
45711dd7afcfSStefano Zampini       Mat benign_global = NULL;
457227b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
45731dd7afcfSStefano Zampini         Mat tmat;
45741dd7afcfSStefano Zampini 
45751dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
45761dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
45771dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
45781dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
45791dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
45801dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
45811dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
45821dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
45831dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
45841dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
45851dd7afcfSStefano Zampini           Mat M;
45861dd7afcfSStefano Zampini 
45871dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
45881dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
45891dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
45901dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
4591906d46d4SStefano Zampini         } else {
45921dd7afcfSStefano Zampini           Mat         eye;
45931dd7afcfSStefano Zampini           PetscScalar *array;
45941dd7afcfSStefano Zampini 
45951dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
45961dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
45971dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
45981dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
4599906d46d4SStefano Zampini           }
46001dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
46011dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46021dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46031dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
46041dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
46051dd7afcfSStefano Zampini         }
46061dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
46071dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
46081dd7afcfSStefano Zampini       }
46091dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
46101dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
46111dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
461227b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
46131dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
46141dd7afcfSStefano Zampini       }
46151dd7afcfSStefano Zampini     }
461616909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
461716909a7fSStefano Zampini       IS             is_global;
461816909a7fSStefano Zampini       const PetscInt *gidxs;
461916909a7fSStefano Zampini 
462016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
462116909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
462216909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
462316909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
462416909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
462516909a7fSStefano Zampini     }
46261dd7afcfSStefano Zampini   }
46271dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
46281dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
4629b9b85e73SStefano Zampini   }
4630a717540cSStefano Zampini 
463172b8c272SStefano Zampini   if (!pcbddc->fake_change) {
46324f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
46334f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
46344f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
46354f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4636019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4637019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
4638019a44ceSStefano Zampini       pcbddc->local_primal_size++;
4639019a44ceSStefano Zampini     }
4640019a44ceSStefano Zampini 
4641019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
4642727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
4643727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
46449f47a83aSStefano 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);
4645c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
46460e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
46479f47a83aSStefano 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);
4648727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4649727cdba6SStefano Zampini       }
46500e6343abSStefano Zampini     }
4651727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4652b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
465372b8c272SStefano Zampini   }
465472b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4655727cdba6SStefano Zampini 
4656a717540cSStefano Zampini   /* flush dbg viewer */
4657b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4658b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4659b8ffe317SStefano Zampini   }
4660a717540cSStefano Zampini 
4661e310c8b4SStefano Zampini   /* free workspace */
4662a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
46634641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
466408122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
46659162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
46669162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
466708122e43SStefano Zampini   } else {
46689162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
46699162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
46709162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
467108122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
467208122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
46739162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
46749162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
467508122e43SStefano Zampini   }
4676674ae819SStefano Zampini   PetscFunctionReturn(0);
4677674ae819SStefano Zampini }
4678674ae819SStefano Zampini 
4679674ae819SStefano Zampini #undef __FUNCT__
4680674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4681674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4682674ae819SStefano Zampini {
4683674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4684674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4685674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
468614f95afaSStefano Zampini   PetscInt    ierr,i,N;
4687674ae819SStefano Zampini 
4688674ae819SStefano Zampini   PetscFunctionBegin;
46898e61c736SStefano Zampini   /* Reset previously computed graph */
46908e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4691674ae819SStefano Zampini   /* Init local Graph struct */
46927fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
46933bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4694674ae819SStefano Zampini 
4695575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
46965099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
46975099eff2SStefano 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);
4698575ad6abSStefano Zampini   }
46999577ea80SStefano Zampini 
4700674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4701d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
47024d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
47034d379d7bSStefano Zampini     PetscInt  nvtxs;
4704e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4705674ae819SStefano Zampini 
47062fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
47072fffb893SStefano Zampini     if (flg_row) {
47084d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4709b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
47102fffb893SStefano Zampini     }
47112fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4712674ae819SStefano Zampini   }
47139b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
47149b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4715674ae819SStefano Zampini   }
4716674ae819SStefano Zampini 
4717674ae819SStefano Zampini   /* Setup of Graph */
471814f95afaSStefano 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);
4719674ae819SStefano Zampini 
47204f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
47214f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
47224f1b2e48SStefano Zampini     PetscInt *local_subs;
47234f1b2e48SStefano Zampini 
47244f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
47254f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
47264f1b2e48SStefano Zampini       const PetscInt *idxs;
47274f1b2e48SStefano Zampini       PetscInt       nl,j;
47284f1b2e48SStefano Zampini 
47294f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
47304f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
47314f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
47324f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
47334f1b2e48SStefano Zampini       }
47344f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
47354f1b2e48SStefano Zampini     }
47364f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
47374f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
47384f1b2e48SStefano Zampini   }
47394f1b2e48SStefano Zampini 
4740674ae819SStefano Zampini   /* Graph's connected components analysis */
4741674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4742674ae819SStefano Zampini   PetscFunctionReturn(0);
4743674ae819SStefano Zampini }
4744674ae819SStefano Zampini 
4745dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4746674ae819SStefano Zampini #undef __FUNCT__
4747674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4748dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4749674ae819SStefano Zampini {
4750dc456d91SStefano Zampini   PetscSF        sf;
4751dc456d91SStefano Zampini   PetscLayout    map;
4752dc456d91SStefano Zampini   const PetscInt *idxs;
4753dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4754dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4755dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4756dc456d91SStefano Zampini   PetscMPIInt    commsize;
4757674ae819SStefano Zampini   PetscBool      first_found;
4758674ae819SStefano Zampini   PetscErrorCode ierr;
4759674ae819SStefano Zampini 
4760674ae819SStefano Zampini   PetscFunctionBegin;
4761dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4762dc456d91SStefano Zampini   if (subset_mult) {
4763dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4764dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4765dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4766674ae819SStefano Zampini   }
4767dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4768dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4769dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4770dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4771dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4772dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4773674ae819SStefano Zampini   }
4774dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4775b2566f29SBarry Smith   ierr = MPIU_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4776dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4777dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4778dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4779dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4780dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4781dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4782dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4783dc456d91SStefano Zampini 
4784dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4785dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4786dc456d91SStefano Zampini   if (subset_mult) {
4787dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4788dc456d91SStefano Zampini 
4789dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4790dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4791dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4792674ae819SStefano Zampini   } else {
4793dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4794674ae819SStefano Zampini   }
4795dc456d91SStefano Zampini   /* local size of new subset */
4796dc456d91SStefano Zampini   n_n = 0;
4797dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4798dc456d91SStefano Zampini 
4799dc456d91SStefano Zampini   /* global indexes in layout */
4800dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4801dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4802dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4803dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4804dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4805dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4806dc456d91SStefano Zampini 
4807dc456d91SStefano Zampini   /* reduce from leaves to roots */
4808dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
480964a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
481064a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4811dc456d91SStefano Zampini 
4812dc456d91SStefano Zampini   /* count indexes in local part of layout */
4813674ae819SStefano Zampini   nlocals = 0;
4814674ae819SStefano Zampini   first_index = -1;
4815674ae819SStefano Zampini   first_found = PETSC_FALSE;
4816dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4817dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4818674ae819SStefano Zampini       first_found = PETSC_TRUE;
4819674ae819SStefano Zampini       first_index = i;
4820674ae819SStefano Zampini     }
4821dc456d91SStefano Zampini     nlocals += root_data[i];
4822674ae819SStefano Zampini   }
4823dc456d91SStefano Zampini 
4824dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
48255fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4826dc456d91SStefano Zampini   start = 0;
482764a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
48285fa240b1SStefano Zampini #else
482964a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
48305fa240b1SStefano Zampini   start = start-nlocals;
48315fa240b1SStefano Zampini #endif
48325fa240b1SStefano Zampini 
4833dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4834dc456d91SStefano Zampini     *N_n = start + nlocals;
4835dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4836dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4837674ae819SStefano Zampini   }
48385fa240b1SStefano Zampini 
48395fa240b1SStefano Zampini   /* adapt root data with cumulative */
4840674ae819SStefano Zampini   if (first_found) {
4841dc456d91SStefano Zampini     PetscInt old_index;
4842dc456d91SStefano Zampini 
4843dc456d91SStefano Zampini     root_data[first_index] += start;
4844674ae819SStefano Zampini     old_index = first_index;
4845dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4846dc456d91SStefano Zampini       if (root_data[i]) {
4847dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4848674ae819SStefano Zampini         old_index = i;
4849674ae819SStefano Zampini       }
4850674ae819SStefano Zampini     }
4851674ae819SStefano Zampini   }
4852dc456d91SStefano Zampini 
4853dc456d91SStefano Zampini   /* from roots to leaves */
4854dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4855dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4856dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4857dc456d91SStefano Zampini 
4858dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4859dc456d91SStefano Zampini   if (subset_mult) {
4860dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4861dc456d91SStefano Zampini     PetscInt        cum;
4862dc456d91SStefano Zampini 
4863dc456d91SStefano Zampini     cum = 0;
4864dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4865dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4866dc456d91SStefano Zampini       PetscInt j;
4867dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4868674ae819SStefano Zampini     }
4869dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4870674ae819SStefano Zampini   } else {
4871dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4872dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4873674ae819SStefano Zampini     }
4874674ae819SStefano Zampini   }
4875dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4876dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4877674ae819SStefano Zampini   PetscFunctionReturn(0);
4878674ae819SStefano Zampini }
48799a7d3425SStefano Zampini 
48809a7d3425SStefano Zampini #undef __FUNCT__
48819a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
48829a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
48839a7d3425SStefano Zampini {
48849a7d3425SStefano Zampini   PetscInt       i,j;
48859a7d3425SStefano Zampini   PetscScalar    *alphas;
48869a7d3425SStefano Zampini   PetscErrorCode ierr;
48879a7d3425SStefano Zampini 
48889a7d3425SStefano Zampini   PetscFunctionBegin;
48899a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4890785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
48919a7d3425SStefano Zampini   for (i=0;i<n;i++) {
48929a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
48939a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
48949a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
48959a7d3425SStefano Zampini   }
48969a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
48979a7d3425SStefano Zampini   PetscFunctionReturn(0);
48989a7d3425SStefano Zampini }
48999a7d3425SStefano Zampini 
4900e7931f94SStefano Zampini #undef __FUNCT__
490170cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
490257de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
4903e7931f94SStefano Zampini {
490457de7509SStefano Zampini   Mat            A;
4905e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4906e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
490752e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
490852e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
490927b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
491057de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
491127b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
491227b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
491327b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
491427b6a85dSStefano Zampini   MPI_Comm       subcomm;
491552e5ac9dSStefano Zampini   PetscErrorCode ierr;
4916a57a6d2fSStefano Zampini 
4917e7931f94SStefano Zampini   PetscFunctionBegin;
491857de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
491957de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
492057de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
492157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
492257de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
492357de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
492457de7509SStefano Zampini 
492557de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
492657de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
492757de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
492857de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
492957de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
493057de7509SStefano Zampini   im_active = !!(n);
493157de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
493257de7509SStefano Zampini   void_procs = size - active_procs;
493357de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
493457de7509SStefano Zampini   if (void_procs) {
493557de7509SStefano Zampini     PetscInt ncand;
493657de7509SStefano Zampini 
493757de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
493857de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
493957de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
494057de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
494157de7509SStefano Zampini       if (!procs_candidates[i]) {
494257de7509SStefano Zampini         procs_candidates[ncand++] = i;
494357de7509SStefano Zampini       }
494457de7509SStefano Zampini     }
494557de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
494657de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
494757de7509SStefano Zampini   }
494857de7509SStefano Zampini 
494957de7509SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix */
495057de7509SStefano Zampini   if (active_procs < *n_subdomains) {
495157de7509SStefano Zampini     PetscInt issize,isidx;
495257de7509SStefano Zampini     if (im_active) {
495357de7509SStefano Zampini       issize = 1;
495457de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
495557de7509SStefano Zampini         isidx = procs_candidates[rank];
495657de7509SStefano Zampini       } else {
495757de7509SStefano Zampini         isidx = rank;
495857de7509SStefano Zampini       }
495957de7509SStefano Zampini     } else {
496057de7509SStefano Zampini       issize = 0;
496157de7509SStefano Zampini       isidx = -1;
496257de7509SStefano Zampini     }
496357de7509SStefano Zampini     *n_subdomains = active_procs;
496457de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
4965daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
496657de7509SStefano Zampini     PetscFunctionReturn(0);
496757de7509SStefano Zampini   }
4968c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
4969c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
497027b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
4971e7931f94SStefano Zampini 
4972e7931f94SStefano Zampini   /* Get info on mapping */
49733bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
49743bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4975e7931f94SStefano Zampini 
4976e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4977785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4978e7931f94SStefano Zampini   xadj[0] = 0;
4979e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4980785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4981785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
498227b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
498327b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
498427b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
498527b6a85dSStefano Zampini       count[shared[i][j]] += 1;
4986e7931f94SStefano Zampini 
498727b6a85dSStefano Zampini   xadj_count = 0;
49882b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
498927b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
499027b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
4991d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4992d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4993d023bfaeSStefano Zampini         xadj_count++;
499427b6a85dSStefano Zampini         break;
499527b6a85dSStefano Zampini       }
4996e7931f94SStefano Zampini     }
4997e7931f94SStefano Zampini   }
4998d023bfaeSStefano Zampini   xadj[1] = xadj_count;
499927b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
50003bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5001e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
5002e7931f94SStefano Zampini 
50033837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
5004e7931f94SStefano Zampini 
500527b6a85dSStefano Zampini   /* Restrict work on active processes only */
500627b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
500727b6a85dSStefano Zampini   if (void_procs) {
500827b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
500927b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
501027b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
501127b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
501227b6a85dSStefano Zampini   } else {
501327b6a85dSStefano Zampini     psubcomm = NULL;
501427b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
501527b6a85dSStefano Zampini   }
501627b6a85dSStefano Zampini 
501727b6a85dSStefano Zampini   v_wgt = NULL;
501827b6a85dSStefano Zampini   if (!color) {
5019e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
5020e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
5021e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5022c8587f34SStefano Zampini   } else {
502352e5ac9dSStefano Zampini     Mat             subdomain_adj;
502452e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
502552e5ac9dSStefano Zampini     MatPartitioning partitioner;
502627b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
502752e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
502857de7509SStefano Zampini     PetscMPIInt     size;
5029b0c7d250SStefano Zampini     PetscBool       aggregate;
5030b0c7d250SStefano Zampini 
503127b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
503227b6a85dSStefano Zampini     if (void_procs) {
503327b6a85dSStefano Zampini       PetscInt prank = rank;
5034785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
503527b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
5036e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
5037e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
5038c8587f34SStefano Zampini       }
5039e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
504027b6a85dSStefano Zampini     } else {
504127b6a85dSStefano Zampini       oldranks = NULL;
504227b6a85dSStefano Zampini     }
5043b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
504427b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
5045b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
5046b0c7d250SStefano Zampini       PetscMPIInt nrank;
5047b0c7d250SStefano Zampini       PetscScalar *vals;
5048b0c7d250SStefano Zampini 
504927b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
5050b0c7d250SStefano Zampini       lrows = 0;
5051b0c7d250SStefano Zampini       if (nrank<redprocs) {
5052b0c7d250SStefano Zampini         lrows = size/redprocs;
5053b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
5054b0c7d250SStefano Zampini       }
505527b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
5056b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
5057b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5058b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5059b0c7d250SStefano Zampini       row = nrank;
5060b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
5061b0c7d250SStefano Zampini       cols = adjncy;
5062b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
5063b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5064b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5065b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5066b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
506752e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
506852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
506952e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5070b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
507127b6a85dSStefano Zampini       if (use_vwgt) {
507227b6a85dSStefano Zampini         Vec               v;
507327b6a85dSStefano Zampini         const PetscScalar *array;
507427b6a85dSStefano Zampini         PetscInt          nl;
507527b6a85dSStefano Zampini 
507627b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
507727b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
507827b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
507927b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
508027b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
508127b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
508227b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
508322db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
508427b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
508527b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
508627b6a85dSStefano Zampini       }
5087b0c7d250SStefano Zampini     } else {
508827b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
508927b6a85dSStefano Zampini       if (use_vwgt) {
509027b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
509127b6a85dSStefano Zampini         v_wgt[0] = local_size;
509227b6a85dSStefano Zampini       }
5093b0c7d250SStefano Zampini     }
509422b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5095e7931f94SStefano Zampini 
5096e7931f94SStefano Zampini     /* Partition */
509727b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5098e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
509927b6a85dSStefano Zampini     if (v_wgt) {
5100e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5101c8587f34SStefano Zampini     }
510257de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
510357de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5104e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5105e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
510622b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5107e7931f94SStefano Zampini 
510852e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
510952e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
511052e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
511152e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
511257de7509SStefano Zampini     if (!aggregate) {
511357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
511427b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
511527b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
511627b6a85dSStefano Zampini #endif
511757de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
511827b6a85dSStefano Zampini       } else if (oldranks) {
5119b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
512027b6a85dSStefano Zampini       } else {
512127b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
512257de7509SStefano Zampini       }
512328143c3dSStefano Zampini     } else {
5124b0c7d250SStefano Zampini       PetscInt    idxs[1];
5125b0c7d250SStefano Zampini       PetscMPIInt tag;
5126b0c7d250SStefano Zampini       MPI_Request *reqs;
5127b0c7d250SStefano Zampini 
5128b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5129b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5130b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
513127b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
513228143c3dSStefano Zampini       }
513327b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5134b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5135b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
513657de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
513727b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
513827b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
513927b6a85dSStefano Zampini #endif
514057de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
514127b6a85dSStefano Zampini       } else if (oldranks) {
5142b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
514327b6a85dSStefano Zampini       } else {
514427b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5145e7931f94SStefano Zampini       }
514657de7509SStefano Zampini     }
514752e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5148e7931f94SStefano Zampini     /* clean up */
5149e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
515052e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5151e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5152e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5153e7931f94SStefano Zampini   }
515427b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
515557de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5156e7931f94SStefano Zampini 
5157e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5158e7931f94SStefano Zampini   i = 1;
515927b6a85dSStefano Zampini   if (!color) i=0;
516057de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5161e7931f94SStefano Zampini   PetscFunctionReturn(0);
5162e7931f94SStefano Zampini }
5163e7931f94SStefano Zampini 
5164e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5165e7931f94SStefano Zampini 
5166e7931f94SStefano Zampini #undef __FUNCT__
5167e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
516857de7509SStefano 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[])
5169e7931f94SStefano Zampini {
517070cf5478SStefano Zampini   Mat                    local_mat;
5171e7931f94SStefano Zampini   IS                     is_sends_internal;
51729d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
517328143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
51749d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
5175e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
5176e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
5177e7931f94SStefano Zampini   const PetscInt*        is_indices;
5178e7931f94SStefano Zampini   MatType                new_local_type;
5179e7931f94SStefano Zampini   /* buffers */
5180e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
518128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
51829d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
5183e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
5184e7931f94SStefano Zampini   /* MPI */
518528143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
518628143c3dSStefano Zampini   PetscSubcomm           subcomm;
5187e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
518828143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
518928143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
519028143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
519128143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
519228143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
5193e7931f94SStefano Zampini   PetscErrorCode         ierr;
5194e7931f94SStefano Zampini 
5195e7931f94SStefano Zampini   PetscFunctionBegin;
519657de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5197e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
519828143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
519957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
520057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
520157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
520257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
520357de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
520457de7509SStefano Zampini 
520557de7509SStefano Zampini   /* further checks */
5206e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5207e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5208e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
5209e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
5210e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
521157de7509SStefano Zampini   if (reuse && *mat_n) {
521270cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
521357de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
521470cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
521528143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
521670cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
521770cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
521870cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
521970cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
522070cf5478SStefano Zampini   }
5221e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
5222e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
522357de7509SStefano Zampini 
5224e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
5225e7931f94SStefano Zampini   if (!is_sends) {
522628143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
522757de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
5228c8587f34SStefano Zampini   } else {
5229e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
5230e7931f94SStefano Zampini     is_sends_internal = is_sends;
5231c8587f34SStefano Zampini   }
5232e7931f94SStefano Zampini 
5233e7931f94SStefano Zampini   /* get comm */
5234a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
5235e7931f94SStefano Zampini 
5236e7931f94SStefano Zampini   /* compute number of sends */
5237e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
5238e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
5239e7931f94SStefano Zampini 
5240e7931f94SStefano Zampini   /* compute number of receives */
5241e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
5242785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
5243e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
5244e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5245e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
5246e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
5247e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
5248e7931f94SStefano Zampini 
524928143c3dSStefano Zampini   /* restrict comm if requested */
525028143c3dSStefano Zampini   subcomm = 0;
525128143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
525228143c3dSStefano Zampini   if (restrict_comm) {
5253779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
5254779c1cceSStefano Zampini 
525528143c3dSStefano Zampini     color = 0;
525653a05cb3SStefano Zampini     if (restrict_full) {
525753a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
525853a05cb3SStefano Zampini     } else {
525953a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
526053a05cb3SStefano Zampini     }
5261b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
526228143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
526328143c3dSStefano Zampini     /* check if reuse has been requested */
526457de7509SStefano Zampini     if (reuse) {
526528143c3dSStefano Zampini       if (*mat_n) {
526628143c3dSStefano Zampini         PetscMPIInt subcommsize2;
526728143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
526828143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
526928143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
527028143c3dSStefano Zampini       } else {
527128143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
527228143c3dSStefano Zampini       }
527328143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
5274779c1cceSStefano Zampini       PetscMPIInt rank;
5275779c1cceSStefano Zampini 
5276779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
527728143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
527828143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
527928143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
5280306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
528128143c3dSStefano Zampini     }
528228143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
528328143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
528428143c3dSStefano Zampini   } else {
528528143c3dSStefano Zampini     comm_n = comm;
528628143c3dSStefano Zampini   }
528728143c3dSStefano Zampini 
5288e7931f94SStefano Zampini   /* prepare send/receive buffers */
5289785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
5290e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
5291785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
5292e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
529328143c3dSStefano Zampini   if (nis) {
5294854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
529528143c3dSStefano Zampini   }
5296e7931f94SStefano Zampini 
529728143c3dSStefano Zampini   /* Get data from local matrices */
52986c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
5299e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
5300e7931f94SStefano Zampini     /*
5301e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
5302e7931f94SStefano Zampini        send_buffer_idxs should contain:
5303e7931f94SStefano Zampini        - MatType_PRIVATE type
5304e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
5305e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
5306e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
5307e7931f94SStefano Zampini     */
53086c4ed002SBarry Smith   else {
5309e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
53103bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
5311854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
5312e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
5313e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
53143bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5315e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
53163bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5317e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
5318e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
5319e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
5320e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
5321c8587f34SStefano Zampini     }
5322c8587f34SStefano Zampini   }
5323e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
532428143c3dSStefano Zampini   /* additional is (if any) */
532528143c3dSStefano Zampini   if (nis) {
532628143c3dSStefano Zampini     PetscMPIInt psum;
532728143c3dSStefano Zampini     PetscInt j;
532828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
532928143c3dSStefano Zampini       PetscInt plen;
533028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
533128143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
533228143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
533328143c3dSStefano Zampini     }
5334854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
533528143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
533628143c3dSStefano Zampini       PetscInt plen;
533728143c3dSStefano Zampini       const PetscInt *is_array_idxs;
533828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
533928143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
534028143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
534128143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
534228143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
534328143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
534428143c3dSStefano Zampini     }
534528143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
534628143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
534728143c3dSStefano Zampini     }
534828143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
534928143c3dSStefano Zampini   }
535028143c3dSStefano Zampini 
5351e7931f94SStefano Zampini   buf_size_idxs = 0;
5352e7931f94SStefano Zampini   buf_size_vals = 0;
535328143c3dSStefano Zampini   buf_size_idxs_is = 0;
5354e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5355e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
5356e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
535728143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
5358e7931f94SStefano Zampini   }
5359785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
5360785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
536195ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
5362e7931f94SStefano Zampini 
5363e7931f94SStefano Zampini   /* get new tags for clean communications */
5364e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
5365e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
536628143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
5367e7931f94SStefano Zampini 
5368e7931f94SStefano Zampini   /* allocate for requests */
5369785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
5370785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
537195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
5372785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
5373785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
537495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
5375e7931f94SStefano Zampini 
5376e7931f94SStefano Zampini   /* communications */
5377e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
5378e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
537928143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
5380e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5381e7931f94SStefano Zampini     source_dest = onodes[i];
5382e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
5383e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
5384e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5385e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
538628143c3dSStefano Zampini     if (nis) {
538757de7509SStefano Zampini       source_dest = onodes_is[i];
538828143c3dSStefano 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);
538928143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
539028143c3dSStefano Zampini     }
5391e7931f94SStefano Zampini   }
5392e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
5393e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
5394e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
5395e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
539628143c3dSStefano Zampini     if (nis) {
539728143c3dSStefano 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);
539828143c3dSStefano Zampini     }
5399e7931f94SStefano Zampini   }
5400e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5401e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
5402e7931f94SStefano Zampini 
5403e7931f94SStefano Zampini   /* assemble new l2g map */
5404e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5405e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
54069d30be91SStefano Zampini   new_local_rows = 0;
5407e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
54089d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5409e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5410e7931f94SStefano Zampini   }
54119d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
5412e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
54139d30be91SStefano Zampini   new_local_rows = 0;
5414e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
54159d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
54169d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5417e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5418e7931f94SStefano Zampini   }
54199d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
54209d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
5421e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
5422e7931f94SStefano Zampini 
5423e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
5424e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
5425e7931f94SStefano 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) */
5426e7931f94SStefano Zampini   if (n_recvs) {
542728143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
5428e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
5429e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
5430e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
5431e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
5432e7931f94SStefano Zampini         break;
5433e7931f94SStefano Zampini       }
5434e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
5435e7931f94SStefano Zampini     }
5436e7931f94SStefano Zampini     switch (new_local_type_private) {
543728143c3dSStefano Zampini       case MATDENSE_PRIVATE:
543828143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
5439e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
5440e7931f94SStefano Zampini           bs = 1;
544128143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
544228143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
544328143c3dSStefano Zampini           bs = 1;
544428143c3dSStefano Zampini         }
5445e7931f94SStefano Zampini         break;
5446e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
5447e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
5448e7931f94SStefano Zampini         bs = 1;
5449e7931f94SStefano Zampini         break;
5450e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
5451e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
5452e7931f94SStefano Zampini         break;
5453e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
5454e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
5455e7931f94SStefano Zampini         break;
5456e7931f94SStefano Zampini       default:
54579d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
5458e7931f94SStefano Zampini         break;
5459e7931f94SStefano Zampini     }
546028143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
546128143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
546228143c3dSStefano Zampini     bs = 1;
5463e7931f94SStefano Zampini   }
5464e7931f94SStefano Zampini 
546570cf5478SStefano Zampini   /* create MATIS object if needed */
546657de7509SStefano Zampini   if (!reuse) {
5467e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
5468e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
546970cf5478SStefano Zampini   } else {
547070cf5478SStefano Zampini     /* it also destroys the local matrices */
547157de7509SStefano Zampini     if (*mat_n) {
547270cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
547357de7509SStefano Zampini     } else { /* this is a fake object */
547457de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
547557de7509SStefano Zampini     }
547670cf5478SStefano Zampini   }
547770cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
5478e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
54799d30be91SStefano Zampini 
54809d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
54819d30be91SStefano Zampini 
54829d30be91SStefano Zampini   /* Global to local map of received indices */
54839d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
54849d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
54859d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
54869d30be91SStefano Zampini 
54879d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
54889d30be91SStefano Zampini   buf_size_idxs = 0;
54899d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
54909d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
54919d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
54929d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
54939d30be91SStefano Zampini   }
54949d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
54959d30be91SStefano Zampini 
54969d30be91SStefano Zampini   /* set preallocation */
54979d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
54989d30be91SStefano Zampini   if (!newisdense) {
54999d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
55009d30be91SStefano Zampini 
55019d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
55029d30be91SStefano Zampini     if (n_recvs) {
55039d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
55049d30be91SStefano Zampini     }
55059d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
55069d30be91SStefano Zampini       PetscInt j;
55079d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
55089d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
55099d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
55109d30be91SStefano Zampini         }
55119d30be91SStefano Zampini       } else {
55129d30be91SStefano Zampini         /* TODO */
55139d30be91SStefano Zampini       }
55149d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
55159d30be91SStefano Zampini     }
55169d30be91SStefano Zampini     if (new_local_nnz) {
55179d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
55189d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
55199d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
55209d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
55219d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
55229d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
55239d30be91SStefano Zampini     } else {
55249d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
55259d30be91SStefano Zampini     }
55269d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
55279d30be91SStefano Zampini   } else {
55289d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
55299d30be91SStefano Zampini   }
5530e7931f94SStefano Zampini 
5531e7931f94SStefano Zampini   /* set values */
5532e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
55339d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5534e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5535e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5536e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
55379d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5538e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5539e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5540e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
554128143c3dSStefano Zampini     } else {
554228143c3dSStefano Zampini       /* TODO */
5543e7931f94SStefano Zampini     }
5544e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5545e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5546e7931f94SStefano Zampini   }
5547e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5548e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
554970cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
555070cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55519d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
55529d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5553e7931f94SStefano Zampini 
5554dfd14d43SStefano Zampini #if 0
555528143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5556e7931f94SStefano Zampini     Vec       lvec,rvec;
5557e7931f94SStefano Zampini     PetscReal infty_error;
5558e7931f94SStefano Zampini 
55592a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5560e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5561e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5562e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
556370cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5564e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5565e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5566e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5567e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5568e7931f94SStefano Zampini   }
556928143c3dSStefano Zampini #endif
5570e7931f94SStefano Zampini 
557128143c3dSStefano Zampini   /* assemble new additional is (if any) */
557228143c3dSStefano Zampini   if (nis) {
557328143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
557428143c3dSStefano Zampini 
557528143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5576854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
557728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
557828143c3dSStefano Zampini     psum = 0;
557928143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
558028143c3dSStefano Zampini       for (j=0;j<nis;j++) {
558128143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
558228143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
558328143c3dSStefano Zampini         psum += plen;
558428143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
558528143c3dSStefano Zampini       }
558628143c3dSStefano Zampini     }
5587854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5588854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
558928143c3dSStefano Zampini     for (i=1;i<nis;i++) {
559028143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
559128143c3dSStefano Zampini     }
559228143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
559328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
559428143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
559528143c3dSStefano Zampini       for (j=0;j<nis;j++) {
559628143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
559728143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
559828143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
559928143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
560028143c3dSStefano Zampini       }
560128143c3dSStefano Zampini     }
560228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
560328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
560428143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
560528143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
560628143c3dSStefano Zampini     }
560728143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
560828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
560928143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
561028143c3dSStefano Zampini   }
5611e7931f94SStefano Zampini   /* free workspace */
561228143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5613e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5614e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5615e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5616e7931f94SStefano Zampini   if (isdense) {
5617e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5618e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5619e7931f94SStefano Zampini   } else {
5620e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5621e7931f94SStefano Zampini   }
562228143c3dSStefano Zampini   if (nis) {
562328143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
562428143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
562528143c3dSStefano Zampini   }
5626e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5627e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
562828143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5629e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5630e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
563128143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5632e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5633e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5634e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5635e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5636e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
563728143c3dSStefano Zampini   if (nis) {
563828143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
563928143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
564028143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
564128143c3dSStefano Zampini   }
564228143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
564328143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
564428143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
564528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
564628143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
564728143c3dSStefano Zampini     }
564853a05cb3SStefano Zampini     *mat_n = NULL;
564928143c3dSStefano Zampini   }
5650e7931f94SStefano Zampini   PetscFunctionReturn(0);
5651e7931f94SStefano Zampini }
5652a57a6d2fSStefano Zampini 
565312edc857SStefano Zampini /* temporary hack into ksp private data structure */
5654af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
565512edc857SStefano Zampini 
5656c8587f34SStefano Zampini #undef __FUNCT__
5657c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5658c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5659c8587f34SStefano Zampini {
5660c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5661c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
566220a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
56639881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
566420a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
56656e683305SStefano Zampini   IS                     coarse_is,*isarray;
56666e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
566730368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5668f9eb5b7dSStefano Zampini   PC                     pc_temp;
5669c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5670c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5671f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
56724f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
56736e683305SStefano Zampini   Mat                    t_coarse_mat_is;
567457de7509SStefano Zampini   PetscInt               ncoarse;
567568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
567622bc73bbSStefano Zampini   PetscScalar            *array;
567757de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
567857de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
56799881197aSStefano Zampini   PetscErrorCode         ierr;
5680fdc09c96SStefano Zampini 
5681c8587f34SStefano Zampini   PetscFunctionBegin;
5682c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
568368457ee5SStefano 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 */
5684fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
56855a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5686fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5687f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5688f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5689f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5690fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
569151bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
569251bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5693dc4bcba2SStefano Zampini         PC        pc;
5694dc4bcba2SStefano Zampini         PetscBool isbddc;
5695dc4bcba2SStefano Zampini 
5696dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5697dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5698dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5699dc4bcba2SStefano Zampini         if (isbddc) {
570063c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
570163c961adSStefano Zampini         } else {
5702727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
570363c961adSStefano Zampini         }
5704fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5705fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5706fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5707f4ddd8eeSStefano Zampini       }
5708fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5709fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5710f4ddd8eeSStefano Zampini     }
571170cf5478SStefano Zampini     /* reset any subassembling information */
571257de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
571370cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
571457de7509SStefano Zampini     }
57156e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5716fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5717f4ddd8eeSStefano Zampini   }
571857de7509SStefano Zampini   /* assemble coarse matrix */
571957de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
572057de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
572157de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
572257de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
572318a45a71SStefano Zampini   } else {
572457de7509SStefano Zampini     coarse_mat = NULL;
572557de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
57266e683305SStefano Zampini   }
5727e7931f94SStefano Zampini 
5728abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5729abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5730abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5731abbbba34SStefano Zampini 
5732abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
573322bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
573422bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
573522bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
573622bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5737e176bc59SStefano 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);
57386e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
57396e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57406e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5741abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5742abbbba34SStefano Zampini 
574357de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
574457de7509SStefano Zampini   im_active = !!(pcis->n);
574557de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
574657de7509SStefano Zampini 
574757de7509SStefano Zampini   /* determine number of process partecipating to coarse solver and compute subassembling pattern */
574857de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
574957de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
575057de7509SStefano Zampini   coarse_mat_is = NULL;
575157de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
575257de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
575357de7509SStefano Zampini   full_restr = PETSC_TRUE;
575457de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(pcbddc->coarse_size,pcbddc->coarse_eqs_per_proc);
575557de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
575657de7509SStefano Zampini   if (multilevel_requested) {
575757de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
575857de7509SStefano Zampini     restr = PETSC_FALSE;
575957de7509SStefano Zampini     full_restr = PETSC_FALSE;
576057de7509SStefano Zampini   } else {
576157de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
576257de7509SStefano Zampini     restr = PETSC_TRUE;
576357de7509SStefano Zampini     full_restr = PETSC_TRUE;
576457de7509SStefano Zampini   }
576557de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
576657de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
576757de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
576857de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
576957de7509SStefano Zampini     PetscInt    psum;
577057de7509SStefano Zampini     PetscMPIInt size;
577157de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
577257de7509SStefano Zampini     else psum = 0;
577357de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
577457de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
577557de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
577657de7509SStefano Zampini   }
577757de7509SStefano Zampini   /* determine if we can go multilevel */
577857de7509SStefano Zampini   if (multilevel_requested) {
577957de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
578057de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
578157de7509SStefano Zampini   }
578257de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
578357de7509SStefano Zampini 
5784e4d548c7SStefano Zampini   /* dump subassembling pattern */
5785e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
5786e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
5787e4d548c7SStefano Zampini   }
5788e4d548c7SStefano Zampini 
57896e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
579027b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
57916e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
57926e683305SStefano Zampini     const PetscInt         *idxs;
57936e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
57946e683305SStefano Zampini 
57956e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
57960be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
57976e683305SStefano Zampini     /* allocate space for temporary storage */
5798854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5799854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
58006e683305SStefano Zampini     /* allocate for IS array */
58016e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
58026e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
580327b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
580430368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5805854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
58066e683305SStefano Zampini     /* dofs splitting */
58076e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
58086e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
58096e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
58106e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
58116e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
58126e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
58136e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
581430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
58156e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
58166e683305SStefano Zampini     }
58176e683305SStefano Zampini     /* neumann boundaries */
58186e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
58196e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
58206e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
58216e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
58226e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
58236e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
58246e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
582530368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
58266e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
58276e683305SStefano Zampini     }
58286e683305SStefano Zampini     /* free memory */
58296e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
58306e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
58316e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
58326e683305SStefano Zampini   } else {
58336e683305SStefano Zampini     nis = 0;
58346e683305SStefano Zampini     nisdofs = 0;
58356e683305SStefano Zampini     nisneu = 0;
583630368db7SStefano Zampini     nisvert = 0;
58376e683305SStefano Zampini     isarray = NULL;
58386e683305SStefano Zampini   }
58396e683305SStefano Zampini   /* destroy no longer needed map */
58406e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
58416e683305SStefano Zampini 
584257de7509SStefano Zampini   /* subassemble */
584357de7509SStefano Zampini   if (multilevel_allowed) {
584457de7509SStefano Zampini     PetscBool reuse,reuser;
584557de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
584657de7509SStefano Zampini     else reuse = PETSC_FALSE;
584757de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
584857de7509SStefano Zampini     if (reuser) {
584957de7509SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray);CHKERRQ(ierr);
585074e2c79eSStefano Zampini     } else {
585157de7509SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
585274e2c79eSStefano Zampini     }
58531f4df5f7SStefano 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 */
585474e2c79eSStefano Zampini   } else {
585557de7509SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
58566e683305SStefano Zampini   }
585757de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
585857de7509SStefano Zampini     PetscMPIInt size;
585957de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
586057de7509SStefano Zampini     if (!multilevel_allowed) {
586157de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
58626e683305SStefano Zampini     } else {
586357de7509SStefano Zampini       Mat A;
5864779c1cceSStefano Zampini 
586557de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
586657de7509SStefano Zampini       if (coarse_mat_is) {
586757de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
586857de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
586957de7509SStefano Zampini         coarse_mat = coarse_mat_is;
587057de7509SStefano Zampini       }
587157de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
587257de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
587357de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
5874779c1cceSStefano Zampini     }
5875779c1cceSStefano Zampini   }
587657de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
587757de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
58786e683305SStefano Zampini 
58796e683305SStefano Zampini   /* create local to global scatters for coarse problem */
588068457ee5SStefano Zampini   if (compute_vecs) {
58816e683305SStefano Zampini     PetscInt lrows;
58826e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
588357de7509SStefano Zampini     if (coarse_mat) {
588457de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
58856e683305SStefano Zampini     } else {
58866e683305SStefano Zampini       lrows = 0;
58876e683305SStefano Zampini     }
58886e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
58896e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
58906e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
58916e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
58926e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
58936e683305SStefano Zampini   }
58946e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
5895c8587f34SStefano Zampini 
5896f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5897f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5898f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5899f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5900f9eb5b7dSStefano Zampini   } else {
5901f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5902f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5903c8587f34SStefano Zampini   }
5904c8587f34SStefano Zampini 
59056e683305SStefano Zampini   /* print some info if requested */
59066e683305SStefano Zampini   if (pcbddc->dbg_flag) {
59076e683305SStefano Zampini     if (!multilevel_allowed) {
59086e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
59096e683305SStefano Zampini       if (multilevel_requested) {
59106e683305SStefano 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);
59116e683305SStefano Zampini       } else if (pcbddc->max_levels) {
59126e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
59136e683305SStefano Zampini       }
59146e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
59156e683305SStefano Zampini     }
59166e683305SStefano Zampini   }
59176e683305SStefano Zampini 
5918f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
591957de7509SStefano Zampini   if (coarse_mat) {
59206a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
59216e683305SStefano Zampini     if (pcbddc->dbg_flag) {
592257de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
59236e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
59246e683305SStefano Zampini     }
5925f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5926312be037SStefano Zampini       char prefix[256],str_level[16];
5927e604994aSStefano Zampini       size_t len;
592857de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5929422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5930c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5931f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
593257de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5933c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
59346e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5935c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5936c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5937e604994aSStefano Zampini       /* prefix */
5938e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5939e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5940e604994aSStefano Zampini       if (!pcbddc->current_level) {
5941e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5942e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5943c8587f34SStefano Zampini       } else {
5944e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5945312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5946312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
594734d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5948312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5949e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5950e604994aSStefano Zampini       }
5951e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
59523e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
59533e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
59543e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
59553e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5956f9eb5b7dSStefano Zampini       /* allow user customization */
5957f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
59583e3c6dadSStefano Zampini     }
59593e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
596051bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
59613e3c6dadSStefano Zampini     if (nisdofs) {
59623e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
59633e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
59643e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
59653e3c6dadSStefano Zampini       }
59663e3c6dadSStefano Zampini     }
59673e3c6dadSStefano Zampini     if (nisneu) {
59683e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
59693e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5970312be037SStefano Zampini     }
597130368db7SStefano Zampini     if (nisvert) {
597230368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
597330368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
597430368db7SStefano Zampini     }
5975f9eb5b7dSStefano Zampini 
5976f9eb5b7dSStefano Zampini     /* get some info after set from options */
5977f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5978f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
59794f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
59806e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5981f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5982f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5983f9eb5b7dSStefano Zampini     }
598439f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
59854f3a063dSStefano Zampini     if (isredundant) {
59864f3a063dSStefano Zampini       KSP inner_ksp;
59874f3a063dSStefano Zampini       PC  inner_pc;
59884f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
59894f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
59904f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
59914f3a063dSStefano Zampini     }
5992f9eb5b7dSStefano Zampini 
599357de7509SStefano Zampini     /* parameters which miss an API */
599457de7509SStefano Zampini     if (isbddc) {
5995720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
5996720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
599757de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
599827b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
599927b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
600027b6a85dSStefano Zampini         pcbddc_coarse->benign_compute_nonetflux = PETSC_TRUE;
6001720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
600259e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
6003720d30f9SStefano Zampini       }
6004d4d8cf7bSStefano Zampini     }
60059881197aSStefano Zampini 
60063301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
60075a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
60083301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
60093301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
60103301b35fSStefano Zampini     }
60113301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
60123301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
60133301b35fSStefano Zampini     }
60143301b35fSStefano Zampini     if (pc->pmat->spd_set) {
60153301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
60163301b35fSStefano Zampini     }
601727b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
601827b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
601927b6a85dSStefano Zampini     }
60206e683305SStefano Zampini     /* set operators */
60215f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
60226e683305SStefano Zampini     if (pcbddc->dbg_flag) {
60236e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
60246e683305SStefano Zampini     }
60256e683305SStefano Zampini   }
60266e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
6027b1ecc7b1SStefano Zampini #if 0
6028b9b85e73SStefano Zampini   {
6029b9b85e73SStefano Zampini     PetscViewer viewer;
6030b9b85e73SStefano Zampini     char filename[256];
6031b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
6032b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
60336a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6034b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
6035f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
6036b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
6037b9b85e73SStefano Zampini   }
6038b9b85e73SStefano Zampini #endif
6039f9eb5b7dSStefano Zampini 
6040b8ffe317SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
6041298c0119SStefano Zampini #if 0
6042b8ffe317SStefano Zampini   if (pcbddc->NullSpace) {
6043b8ffe317SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
604498a51de6SStefano Zampini   }
6045298c0119SStefano Zampini #endif
6046b0f5fe93SStefano Zampini   /* hack */
604798a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
604898a51de6SStefano Zampini     Vec crhs,csol;
604904708bb6SStefano Zampini 
6050f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
6051f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
6052f347579bSStefano Zampini     if (!csol) {
60532a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
6054f9eb5b7dSStefano Zampini     }
6055f347579bSStefano Zampini     if (!crhs) {
60562a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
6057f347579bSStefano Zampini     }
6058b0f5fe93SStefano Zampini   }
6059b0f5fe93SStefano Zampini 
6060b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
6061b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
6062b0f5fe93SStefano Zampini 
6063b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
60644f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
60654f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
60664f1b2e48SStefano Zampini     }
6067b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
6068b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
6069b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6070b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6071b0f5fe93SStefano Zampini     if (coarse_mat) {
6072b0f5fe93SStefano Zampini       Vec         nullv;
6073b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
6074b0f5fe93SStefano Zampini       PetscInt    nl;
6075b0f5fe93SStefano Zampini 
6076b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
6077b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
6078b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6079b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
6080b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
6081b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
6082b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6083b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
6084b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
6085b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
6086b0f5fe93SStefano Zampini     }
6087b0f5fe93SStefano Zampini   }
6088b0f5fe93SStefano Zampini 
6089b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
6090b0f5fe93SStefano Zampini     PetscBool ispreonly;
6091b0f5fe93SStefano Zampini 
6092b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
6093b0f5fe93SStefano Zampini       PetscBool isnull;
6094b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
609527b6a85dSStefano Zampini       if (0) {
609630368db7SStefano Zampini         if (isbddc && !pcbddc->benign_saddle_point) {
6097b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
6098b0f5fe93SStefano Zampini         } else {
6099b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
6100b0f5fe93SStefano Zampini         }
6101b0f5fe93SStefano Zampini       } else {
6102b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6103b0f5fe93SStefano Zampini       }
6104b0f5fe93SStefano Zampini     }
6105b0f5fe93SStefano Zampini     /* setup coarse ksp */
6106b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
6107cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
6108cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
61096e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
6110c8587f34SStefano Zampini       KSP       check_ksp;
61112b510759SStefano Zampini       KSPType   check_ksp_type;
6112c8587f34SStefano Zampini       PC        check_pc;
61136e683305SStefano Zampini       Vec       check_vec,coarse_vec;
61146a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
61152b510759SStefano Zampini       PetscInt  its;
61166e683305SStefano Zampini       PetscBool compute_eigs;
61176e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
61186e683305SStefano Zampini       PetscInt  neigs;
61198e185a42SStefano Zampini       const char *prefix;
6120c8587f34SStefano Zampini 
61212b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
61226e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
6123422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
612423ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6125f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
6126e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
6127e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
6128e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
61292b510759SStefano Zampini       if (ispreonly) {
61302b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
61316e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
61322b510759SStefano Zampini       } else {
6133cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
61346e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
6135c8587f34SStefano Zampini       }
6136c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
61376e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
61386e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
61396e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
6140a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
6141a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
6142a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
6143a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
6144c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
6145c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
6146c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
6147c8587f34SStefano Zampini       /* create random vec */
61482701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
6149c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
6150c8587f34SStefano Zampini       if (CoarseNullSpace) {
6151c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
6152c8587f34SStefano Zampini       }
61536e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
6154c8587f34SStefano Zampini       /* solve coarse problem */
61556e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
6156c8587f34SStefano Zampini       if (CoarseNullSpace) {
61576e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
6158c8587f34SStefano Zampini       }
6159cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
61606e683305SStefano Zampini       if (compute_eigs) {
6161854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
6162854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
61636e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
61646e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
61656e683305SStefano Zampini         lambda_min = eigs_r[0];
61666e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
61672701bc32SStefano Zampini           if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
61682701bc32SStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
6169cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
6170cbcc2c2aSStefano Zampini           }
6171c8587f34SStefano Zampini         }
6172c8587f34SStefano Zampini       }
6173cbcc2c2aSStefano Zampini 
6174c8587f34SStefano Zampini       /* check coarse problem residual error */
61756e683305SStefano Zampini       if (pcbddc->dbg_flag) {
61766e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
61776e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
61786e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
6179c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
61806e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
61816e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
6182779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
61836e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
61846e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
61856e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
61866e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
6187b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
6188b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
6189b0f5fe93SStefano Zampini         }
61906e683305SStefano Zampini         if (compute_eigs) {
61916e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
6192deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
6193c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
61946e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
61956e683305SStefano 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);
61966e683305SStefano Zampini           for (i=0;i<neigs;i++) {
61976e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
6198c8587f34SStefano Zampini           }
61996e683305SStefano Zampini         }
62006e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
62016e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
62026e683305SStefano Zampini       }
6203e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
62042701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
6205c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
62066e683305SStefano Zampini       if (compute_eigs) {
62076e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
62086e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
6209c8587f34SStefano Zampini       }
62106e683305SStefano Zampini     }
62116e683305SStefano Zampini   }
6212cbcc2c2aSStefano Zampini   /* print additional info */
6213cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
62146e683305SStefano Zampini     /* waits until all processes reaches this point */
62156e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
6216cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
6217cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6218cbcc2c2aSStefano Zampini   }
6219cbcc2c2aSStefano Zampini 
62202b510759SStefano Zampini   /* free memory */
6221c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6222fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
6223c8587f34SStefano Zampini   PetscFunctionReturn(0);
6224c8587f34SStefano Zampini }
6225674ae819SStefano Zampini 
6226f34684f1SStefano Zampini #undef __FUNCT__
6227f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
6228f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
6229f34684f1SStefano Zampini {
6230f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6231f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
6232f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
6233dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
6234dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
623573be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
6236dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
6237f34684f1SStefano Zampini   PetscErrorCode ierr;
6238f34684f1SStefano Zampini 
6239f34684f1SStefano Zampini   PetscFunctionBegin;
6240f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
62416c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
6242dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
62433bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
6244dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6245dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
6246dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
6247dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
6248dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
6249dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
62506c4ed002SBarry 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);
6251dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
6252dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6253dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
6254dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6255dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6256f34684f1SStefano Zampini 
6257f34684f1SStefano Zampini   /* check numbering */
6258f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
6259019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
6260dc456d91SStefano Zampini     PetscInt    i;
6261b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
6262f34684f1SStefano Zampini 
6263f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6264f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
6265f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
62661575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6267019a44ceSStefano Zampini     /* counter */
6268019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6269019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6270019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6271019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6272019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6273019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6274f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
6275f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
6276727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6277f34684f1SStefano Zampini     }
6278f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6279f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6280f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6281e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6282e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6283e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6284e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6285f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6286019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6287f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6288019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
62892c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
629075c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
6291b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
62922c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
62932c66d082SStefano 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);
6294f34684f1SStefano Zampini       }
6295f34684f1SStefano Zampini     }
6296019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6297b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
6298f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6299f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6300f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
6301f34684f1SStefano Zampini     }
6302f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6303f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6304e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6305e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6306f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
6307f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
6308b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
6309ca8b9ea9SStefano Zampini       PetscInt *gidxs;
6310ca8b9ea9SStefano Zampini 
6311ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
63123bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
6313f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
6314f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6315f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6316f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
63174bc2dc4bSStefano 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);
6318f34684f1SStefano Zampini       }
6319f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6320ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
6321f34684f1SStefano Zampini     }
6322f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
63231575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6324302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
6325f34684f1SStefano Zampini   }
63268bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
6327f34684f1SStefano Zampini   /* get back data */
6328f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
6329f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
6330674ae819SStefano Zampini   PetscFunctionReturn(0);
6331674ae819SStefano Zampini }
6332674ae819SStefano Zampini 
6333e456f2a8SStefano Zampini #undef __FUNCT__
6334e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
6335a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
6336e456f2a8SStefano Zampini {
6337e456f2a8SStefano Zampini   IS             localis_t;
6338a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
6339e456f2a8SStefano Zampini   PetscScalar    *vals;
6340e456f2a8SStefano Zampini   PetscErrorCode ierr;
6341e456f2a8SStefano Zampini 
6342e456f2a8SStefano Zampini   PetscFunctionBegin;
6343a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
6344e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
6345854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
6346e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
6347e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6348a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
6349a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
63501035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
6351a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
63521035eff8SStefano Zampini   }
6353a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
6354e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6355e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
6356a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
6357a7dc3881SStefano Zampini   /* now compute set in local ordering */
6358a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6359a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6360a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6361a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
6362a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6363ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6364e456f2a8SStefano Zampini       lsize++;
6365e456f2a8SStefano Zampini     }
6366e456f2a8SStefano Zampini   }
6367854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
6368a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6369ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6370e456f2a8SStefano Zampini       idxs[lsize++] = i;
6371e456f2a8SStefano Zampini     }
6372e456f2a8SStefano Zampini   }
6373a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6374a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
6375e456f2a8SStefano Zampini   *localis = localis_t;
6376e456f2a8SStefano Zampini   PetscFunctionReturn(0);
6377e456f2a8SStefano Zampini }
6378906d46d4SStefano Zampini 
6379b96c3477SStefano Zampini #undef __FUNCT__
6380b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
638108122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6382b96c3477SStefano Zampini {
6383a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6384b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6385b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6386a64f4aa4SStefano Zampini   Mat                 S_j;
6387b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6388b96c3477SStefano Zampini   PetscBool           free_used_adj;
6389b96c3477SStefano Zampini   PetscErrorCode      ierr;
6390b96c3477SStefano Zampini 
6391b96c3477SStefano Zampini   PetscFunctionBegin;
6392b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6393b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
639408122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6395b96c3477SStefano Zampini     used_xadj = NULL;
6396b96c3477SStefano Zampini     used_adjncy = NULL;
6397b96c3477SStefano Zampini   } else {
639808122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
639908122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
640008122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
640108122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6402b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6403b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6404b96c3477SStefano Zampini     } else {
64052fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6406b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6407b96c3477SStefano Zampini       PetscInt       nvtxs;
6408b96c3477SStefano Zampini 
64092fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
64102fffb893SStefano Zampini       if (flg_row) {
6411b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6412b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6413b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6414b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
64152fffb893SStefano Zampini       } else {
64162fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
64172fffb893SStefano Zampini         used_xadj = NULL;
64182fffb893SStefano Zampini         used_adjncy = NULL;
64192fffb893SStefano Zampini       }
64202fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6421b96c3477SStefano Zampini     }
6422b96c3477SStefano Zampini   }
6423d5574798SStefano Zampini 
6424d5574798SStefano Zampini   /* setup sub_schurs data */
6425a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6426df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6427df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6428a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
642991af6908SStefano 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);
6430a64f4aa4SStefano Zampini   } else {
64316816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
6432b7ab4a40SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;;
6433a3df083aSStefano Zampini     PetscInt  benign_n;
643472b8c272SStefano Zampini     Mat       change = NULL;
64359d54b7f4SStefano Zampini     Vec       scaling = NULL;
643672b8c272SStefano Zampini     IS        change_primal = NULL;
6437a3df083aSStefano Zampini 
64385feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
64395feab87aSStefano Zampini       PetscInt n_vertices;
64405feab87aSStefano Zampini 
64415feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
64422034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
64435feab87aSStefano Zampini     }
644404708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
644504708bb6SStefano Zampini     if (!isseqaij) {
644604708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
644704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
644804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
644904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
645004708bb6SStefano Zampini       } else {
6451511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
645204708bb6SStefano Zampini       }
645304708bb6SStefano Zampini     }
6454a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6455a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6456ca92afb2SStefano Zampini     } else {
6457a3df083aSStefano Zampini       benign_n = 0;
6458ca92afb2SStefano Zampini     }
6459b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
6460b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
6461b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
646272b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
646322db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
6464b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
646522db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
6466b7ab4a40SStefano Zampini     }
6467b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
6468b7ab4a40SStefano 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 */
6469b7ab4a40SStefano Zampini     if (need_change) {
647088c03ad3SStefano Zampini       PC_IS   *pcisf;
647188c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
647288c03ad3SStefano Zampini       PC      pcf;
647388c03ad3SStefano Zampini 
6474e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
647588c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
647688c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
647788c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
647888c03ad3SStefano Zampini       /* hacks */
647988c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
648072b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
648172b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
648272b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
648372b8c272SStefano Zampini       pcisf->n = pcis->n;
648472b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
648588c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
648688c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
648788c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
648888c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
648988c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
649088c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
649172b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
649288c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
649388c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
649472b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
649572b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
649672b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
649772b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
649872b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
649988c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
650072b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
650188c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
650288c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
650388c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
650488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
650588c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
650688c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
650788c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
650888c03ad3SStefano Zampini     }
65099d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
651091af6908SStefano 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);
651172b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
651272b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
6513ca92afb2SStefano Zampini   }
6514d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6515b96c3477SStefano Zampini 
6516b96c3477SStefano Zampini   /* free adjacency */
6517b96c3477SStefano Zampini   if (free_used_adj) {
6518b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6519b96c3477SStefano Zampini   }
6520b96c3477SStefano Zampini   PetscFunctionReturn(0);
6521b96c3477SStefano Zampini }
6522b96c3477SStefano Zampini 
6523b96c3477SStefano Zampini #undef __FUNCT__
6524b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
652508122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6526b96c3477SStefano Zampini {
6527b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6528b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6529b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6530b96c3477SStefano Zampini   PCBDDCGraph         graph;
6531b96c3477SStefano Zampini   PetscErrorCode      ierr;
6532b96c3477SStefano Zampini 
6533b96c3477SStefano Zampini   PetscFunctionBegin;
6534b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
653508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
65363301b35fSStefano Zampini     IS       verticesIS,verticescomm;
65373301b35fSStefano Zampini     PetscInt vsize,*idxs;
6538b96c3477SStefano Zampini 
6539b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
65403301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
65413301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
65423301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
65433301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
65443301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6545b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
65467fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
6547441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
65483301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6549b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6550b96c3477SStefano Zampini   } else {
6551b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6552b96c3477SStefano Zampini   }
6553e4d548c7SStefano Zampini   /* print some info */
6554e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
6555e4d548c7SStefano Zampini     IS       vertices;
6556e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
6557e4d548c7SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6558e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
6559e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
6560e4d548c7SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
6561e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6562e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6563e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
6564e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
6565e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
6566e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6567e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6568e4d548c7SStefano Zampini   }
6569b96c3477SStefano Zampini 
6570b96c3477SStefano Zampini   /* sub_schurs init */
6571a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6572a64f4aa4SStefano Zampini 
6573b96c3477SStefano Zampini   /* free graph struct */
657408122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6575b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6576b96c3477SStefano Zampini   }
6577b96c3477SStefano Zampini   PetscFunctionReturn(0);
6578b96c3477SStefano Zampini }
6579fa34dd3eSStefano Zampini 
6580fa34dd3eSStefano Zampini #undef __FUNCT__
6581fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6582fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6583fa34dd3eSStefano Zampini {
6584fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6585fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6586fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6587fa34dd3eSStefano Zampini 
6588fa34dd3eSStefano Zampini   PetscFunctionBegin;
6589fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6590fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
65914f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6592fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
65934f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
659475c01103SStefano Zampini     PetscReal      norm;
6595fa34dd3eSStefano Zampini     PetscInt       i;
6596fa34dd3eSStefano Zampini 
6597fa34dd3eSStefano Zampini     /* B0 and B0_B */
6598fa34dd3eSStefano Zampini     if (zerodiag) {
6599fa34dd3eSStefano Zampini       IS       dummy;
6600fa34dd3eSStefano Zampini 
66014f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
66024f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6603fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6604fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6605fa34dd3eSStefano Zampini     }
6606fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6607fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6608fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6609fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6610fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6611fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6612fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6613fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6614fa34dd3eSStefano Zampini     /* S_j */
6615fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6616fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6617fa34dd3eSStefano Zampini 
6618fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6619fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6620fa34dd3eSStefano Zampini     /* continuous in primal space */
6621fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6622fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6623fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6624fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
66254f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
66264f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6627fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6628fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6629fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6630fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6631fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6632fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6633fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6634fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6635fa34dd3eSStefano Zampini 
6636fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6637fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6638fa34dd3eSStefano Zampini     /* local with Schur */
6639fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6640fa34dd3eSStefano Zampini     if (zerodiag) {
6641fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
66424f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6643fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6644fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6645fa34dd3eSStefano Zampini     }
6646fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6647fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6648fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6649fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6650fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6651fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6652fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6653fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6654fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6655fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6656fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6657fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6658fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6659fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6660fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6661fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6662fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6663fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6664fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6665fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6666fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6667fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6668fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6669fa34dd3eSStefano Zampini     if (zerodiag) {
6670fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6671fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
66724f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6673fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6674fa34dd3eSStefano Zampini     }
6675fa34dd3eSStefano Zampini     /* BDDC */
6676fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6677fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6678fa34dd3eSStefano Zampini 
6679fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6680fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6681fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6682fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
66834f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
66844f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6685fa34dd3eSStefano Zampini     }
66864f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6687fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6688fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6689fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6690fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6691fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6692fa34dd3eSStefano Zampini   }
6693fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6694fa34dd3eSStefano Zampini }
6695