xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 75c01103f2819f4a39b108c2eabb426c649b60cd)
1ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
3674ae819SStefano Zampini #include <petscblaslapack.h>
4674ae819SStefano Zampini 
5906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y);
6906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y);
7906d46d4SStefano Zampini 
8674ae819SStefano Zampini #undef __FUNCT__
95408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
105408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
115408967cSStefano Zampini {
125408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
135408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
14dee84bffSStefano Zampini   IS             dirIS = NULL;
155408967cSStefano Zampini   PetscErrorCode ierr;
165408967cSStefano Zampini 
175408967cSStefano Zampini   PetscFunctionBegin;
18dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
195408967cSStefano Zampini   if (zerodiag) {
205408967cSStefano Zampini     Mat            A;
215408967cSStefano Zampini     Vec            vec3_N;
225408967cSStefano Zampini     PetscScalar    *vals;
235408967cSStefano Zampini     const PetscInt *idxs;
245408967cSStefano Zampini     PetscInt       i,nz;
255408967cSStefano Zampini 
265408967cSStefano Zampini     /* p0 */
275408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
285408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
295408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
305408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
315408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.; /* TODO add quadrature */
325408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
335408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
345408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
355408967cSStefano Zampini     /* v_I */
365408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
375408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
385408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
395408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
405408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
415408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
425408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
435408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
445408967cSStefano Zampini     if (dirIS) {
455408967cSStefano Zampini       PetscInt n;
465408967cSStefano Zampini 
475408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
485408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
495408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
505408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
515408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
525408967cSStefano Zampini     }
535408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
545408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
555408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
565408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
575408967cSStefano Zampini     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
585408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
595408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
605408967cSStefano Zampini     if (PetscAbsScalar(vals[0]) > PETSC_SMALL) { /* TODO: should I add the A-norm in test? */
615408967cSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! b(v_I,p_0) = %f (should be numerically 0.)",PetscAbsScalar(vals[0]));
625408967cSStefano Zampini     }
635408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
645408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
655408967cSStefano Zampini   }
66dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
675408967cSStefano Zampini 
685408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
695408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
705408967cSStefano Zampini   pcbddc->benign_p0 = -PetscGlobalRank;
715408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
725408967cSStefano Zampini   pcbddc->benign_p0 = 1;
735408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
74*75c01103SStefano Zampini   if (pcbddc->benign_p0_gidx >=0 && (PetscInt)PetscRealPart(pcbddc->benign_p0) != -PetscGlobalRank) {
755408967cSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %1.4e instead of %1.4e\n",pcbddc->benign_p0,-PetscGlobalRank);CHKERRQ(ierr);
765408967cSStefano Zampini   }
775408967cSStefano Zampini   PetscFunctionReturn(0);
785408967cSStefano Zampini }
795408967cSStefano Zampini 
805408967cSStefano Zampini #undef __FUNCT__
81339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
82339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
83339f8db1SStefano Zampini {
84339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8540fa8d13SStefano Zampini   IS             pressures,zerodiag;
86b0f5fe93SStefano Zampini   PetscInt       nz,n;
87b0f5fe93SStefano Zampini   PetscBool      sorted,have_null;
88339f8db1SStefano Zampini   PetscErrorCode ierr;
89339f8db1SStefano Zampini 
90339f8db1SStefano Zampini   PetscFunctionBegin;
91339f8db1SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
92339f8db1SStefano Zampini   ierr = PetscObjectReference((PetscObject)pcbddc->local_mat);CHKERRQ(ierr);
93339f8db1SStefano Zampini   pcbddc->benign_original_mat = pcbddc->local_mat;
9440fa8d13SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures", otherwise, uses only zerodiagonal dofs (ok if the pressure block is all zero) */
9540fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
9640fa8d13SStefano Zampini     PetscInt p = pcbddc->n_ISForDofsLocal-1;
9740fa8d13SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[p]);CHKERRQ(ierr);
9840fa8d13SStefano Zampini     pressures = pcbddc->ISForDofsLocal[p];
9940fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
10040fa8d13SStefano Zampini     if (!sorted) {
10140fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
10240fa8d13SStefano Zampini     }
10340fa8d13SStefano Zampini   } else {
10440fa8d13SStefano Zampini     pressures = NULL;
10540fa8d13SStefano Zampini   }
106339f8db1SStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->benign_original_mat,&zerodiag);CHKERRQ(ierr);
107339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
108339f8db1SStefano Zampini   if (!sorted) {
109339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
110339f8db1SStefano Zampini   }
11140fa8d13SStefano Zampini   /*
11240fa8d13SStefano Zampini      Check if all the pressure dofs have a zero diagonal
11340fa8d13SStefano Zampini      If not, a change of basis on pressures is not needed
11440fa8d13SStefano Zampini      since the local Schur complements are SPD
11540fa8d13SStefano Zampini   */
116339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
11740fa8d13SStefano Zampini   if (pressures) {
11840fa8d13SStefano Zampini     PetscInt  np;
11940fa8d13SStefano Zampini     PetscBool sameis;
12040fa8d13SStefano Zampini 
12140fa8d13SStefano Zampini     sameis = PETSC_FALSE;
12240fa8d13SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
12340fa8d13SStefano Zampini     if (nz == np) {
12440fa8d13SStefano Zampini       const PetscInt *idxs,*pidxs;
12540fa8d13SStefano Zampini 
12640fa8d13SStefano Zampini       ierr = ISGetIndices(pressures,&pidxs);CHKERRQ(ierr);
12740fa8d13SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
12840fa8d13SStefano Zampini       ierr = PetscMemcmp(pidxs,idxs,np*sizeof(PetscInt),&sameis);CHKERRQ(ierr);
12940fa8d13SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
13040fa8d13SStefano Zampini       ierr = ISRestoreIndices(pressures,&pidxs);CHKERRQ(ierr);
13140fa8d13SStefano Zampini     }
13240fa8d13SStefano Zampini     if (!sameis) { /* destroy index sets and set nz to 0 to avoid next code branch */
13340fa8d13SStefano Zampini       ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
13440fa8d13SStefano Zampini       nz = 0;
13540fa8d13SStefano Zampini     }
13640fa8d13SStefano Zampini     ierr = ISDestroy(&pressures);CHKERRQ(ierr);
13740fa8d13SStefano Zampini   }
138339f8db1SStefano Zampini   if (nz) {
139339f8db1SStefano Zampini     IS                zerodiagc;
140339f8db1SStefano Zampini     PetscScalar       *array;
141339f8db1SStefano Zampini     const PetscInt    *idxs,*idxsc;
142b0f5fe93SStefano Zampini     PetscInt          i,*nnz;
143339f8db1SStefano Zampini 
144339f8db1SStefano Zampini     /* TODO: add check for shared dofs and raise error */
145339f8db1SStefano Zampini     ierr = MatGetLocalSize(pcbddc->benign_original_mat,&n,NULL);CHKERRQ(ierr);
146339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
147339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
148339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
149339f8db1SStefano Zampini     /* local change of basis for pressures */
150339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
151339f8db1SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->benign_original_mat),&pcbddc->benign_change);CHKERRQ(ierr);
152339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
153339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
154339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
155339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities */
156339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) nnz[idxs[i]] = 2; /* change on pressures */
157339f8db1SStefano Zampini     nnz[idxs[nz-1]] = nz; /* last local pressure dof: _0 set */
158339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
159339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
160339f8db1SStefano Zampini     /* set identity on velocities */
161339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
162339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
163339f8db1SStefano Zampini     }
164339f8db1SStefano Zampini     /* set change on pressures */
165339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) {
166339f8db1SStefano Zampini       PetscScalar vals[2];
167339f8db1SStefano Zampini       PetscInt    cols[2];
168339f8db1SStefano Zampini 
169339f8db1SStefano Zampini       /* TODO: add quadrature */
170339f8db1SStefano Zampini       cols[0] = idxs[i];
171339f8db1SStefano Zampini       cols[1] = idxs[nz-1];
172339f8db1SStefano Zampini       vals[0] = 1.;
173b0f5fe93SStefano Zampini       vals[1] = 1.;
174339f8db1SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+i,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
175339f8db1SStefano Zampini     }
176339f8db1SStefano Zampini     ierr = PetscMalloc1(nz,&array);CHKERRQ(ierr);
177339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) array[i] = -1.;
178b0f5fe93SStefano Zampini     array[nz-1] = 1.;
179339f8db1SStefano Zampini     ierr = MatSetValues(pcbddc->benign_change,1,idxs+nz-1,nz,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
180339f8db1SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
181339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
182339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
183339f8db1SStefano Zampini     /* TODO: need optimization? */
184339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
185339f8db1SStefano Zampini     ierr = MatPtAP(pcbddc->benign_original_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
186339f8db1SStefano Zampini     /* store local and global idxs for p0 */
187339f8db1SStefano Zampini     pcbddc->benign_p0_lidx = idxs[nz-1];
188339f8db1SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,1,&idxs[nz-1],&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
189339f8db1SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
190339f8db1SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
191339f8db1SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
192b0f5fe93SStefano Zampini   } else { /* if nz == 0, destroy local IS */
193b0f5fe93SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
194339f8db1SStefano Zampini   }
195b0f5fe93SStefano Zampini 
196b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
197b0f5fe93SStefano Zampini   ierr = MatGetLocalSize(pcbddc->benign_original_mat,&n,NULL);CHKERRQ(ierr);
198b0f5fe93SStefano Zampini   have_null = PETSC_TRUE;
199b0f5fe93SStefano Zampini   if (!zerodiag && n) have_null = PETSC_FALSE;
200b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
201339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
202339f8db1SStefano Zampini   PetscFunctionReturn(0);
203339f8db1SStefano Zampini }
204339f8db1SStefano Zampini 
205339f8db1SStefano Zampini #undef __FUNCT__
206015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
207015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
208efc2fbd9SStefano Zampini {
209efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
210efc2fbd9SStefano Zampini   PetscErrorCode ierr;
211efc2fbd9SStefano Zampini 
212efc2fbd9SStefano Zampini   PetscFunctionBegin;
213efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
214efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
215c9ed8603SStefano Zampini     if (pcbddc->benign_p0_gidx >= 0) {
216efc2fbd9SStefano Zampini       ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,1,NULL,PETSC_OWN_POINTER,&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
217c9ed8603SStefano Zampini     } else {
218c9ed8603SStefano Zampini       ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,0,NULL,PETSC_OWN_POINTER,&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
219c9ed8603SStefano Zampini     }
220efc2fbd9SStefano Zampini   }
221015636ebSStefano Zampini   if (get) { /* use SF to get values */
222efc2fbd9SStefano Zampini     PetscScalar *array;
223efc2fbd9SStefano Zampini 
224efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
225efc2fbd9SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,&pcbddc->benign_p0);CHKERRQ(ierr);
226efc2fbd9SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,&pcbddc->benign_p0);CHKERRQ(ierr);
227efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
228efc2fbd9SStefano Zampini   } else { /* use VecSetValue */
229c9ed8603SStefano Zampini     if (pcbddc->benign_p0_gidx >= 0) {
230efc2fbd9SStefano Zampini       ierr = VecSetValue(v,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
231c9ed8603SStefano Zampini     }
232efc2fbd9SStefano Zampini     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
233efc2fbd9SStefano Zampini     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
234efc2fbd9SStefano Zampini   }
235efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
236efc2fbd9SStefano Zampini }
237efc2fbd9SStefano Zampini 
238efc2fbd9SStefano Zampini #undef __FUNCT__
239c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
240c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
241c263805aSStefano Zampini {
242c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
243c263805aSStefano Zampini   PetscErrorCode ierr;
244c263805aSStefano Zampini 
245c263805aSStefano Zampini   PetscFunctionBegin;
246c263805aSStefano Zampini   /* TODO: add error checking
247c263805aSStefano Zampini     - avoid nested pop (or push) calls.
248c263805aSStefano Zampini     - cannot push before pop.
2491c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
250c263805aSStefano Zampini   */
251c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx < 0) {
252efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
253efc2fbd9SStefano Zampini   }
254c263805aSStefano Zampini   if (pop) {
255c263805aSStefano Zampini     const PetscInt    *cB0_cols;
256c263805aSStefano Zampini     PetscInt          cB0_ncol;
257c263805aSStefano Zampini     const PetscScalar *cB0_vals;
258c263805aSStefano Zampini 
259c263805aSStefano Zampini     /* extract B_0 */
260efc2fbd9SStefano Zampini     ierr = MatGetRow(pcbddc->local_mat,pcbddc->benign_p0_lidx,&cB0_ncol,&cB0_cols,&cB0_vals);CHKERRQ(ierr);
261c263805aSStefano Zampini     pcbddc->B0_ncol = cB0_ncol;
262c263805aSStefano Zampini     ierr = PetscFree2(pcbddc->B0_cols,pcbddc->B0_vals);CHKERRQ(ierr);
263c263805aSStefano Zampini     ierr = PetscMalloc2(cB0_ncol,&pcbddc->B0_cols,cB0_ncol,&pcbddc->B0_vals);CHKERRQ(ierr);
264c263805aSStefano Zampini     ierr = PetscMemcpy(pcbddc->B0_cols,cB0_cols,cB0_ncol*sizeof(PetscInt));CHKERRQ(ierr);
265c263805aSStefano Zampini     ierr = PetscMemcpy(pcbddc->B0_vals,cB0_vals,cB0_ncol*sizeof(PetscScalar));CHKERRQ(ierr);
266efc2fbd9SStefano Zampini     ierr = MatRestoreRow(pcbddc->local_mat,pcbddc->benign_p0_lidx,&cB0_ncol,&cB0_cols,&cB0_vals);CHKERRQ(ierr);
267c263805aSStefano Zampini     /* remove rows and cols from local problem */
268c263805aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
269efc2fbd9SStefano Zampini     ierr = MatZeroRowsColumns(pcbddc->local_mat,1,&pcbddc->benign_p0_lidx,1.,NULL,NULL);CHKERRQ(ierr);
270c263805aSStefano Zampini   } else { /* push */
271efc2fbd9SStefano Zampini     ierr = MatSetValues(pcbddc->local_mat,1,&pcbddc->benign_p0_lidx,pcbddc->B0_ncol,pcbddc->B0_cols,pcbddc->B0_vals,INSERT_VALUES);CHKERRQ(ierr);
272efc2fbd9SStefano Zampini     ierr = MatSetValues(pcbddc->local_mat,pcbddc->B0_ncol,pcbddc->B0_cols,1,&pcbddc->benign_p0_lidx,pcbddc->B0_vals,INSERT_VALUES);CHKERRQ(ierr);
273efc2fbd9SStefano Zampini     ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx,pcbddc->benign_p0_lidx,0.0,INSERT_VALUES);CHKERRQ(ierr);
274c263805aSStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
275c263805aSStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
276c263805aSStefano Zampini   }
277c263805aSStefano Zampini   PetscFunctionReturn(0);
278c263805aSStefano Zampini }
279c263805aSStefano Zampini 
280c263805aSStefano Zampini #undef __FUNCT__
281b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
28208122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
283b1b3d7a2SStefano Zampini {
284b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
28508122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
28608122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
28708122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
28808122e43SStefano Zampini   PetscScalar     *work,lwork;
28908122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
29008122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
29108122e43SStefano Zampini   PetscReal       *eigs,thresh;
2921b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
293f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
29408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
29508122e43SStefano Zampini   PetscReal       *rwork;
29608122e43SStefano Zampini #endif
297b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
298b1b3d7a2SStefano Zampini 
299b1b3d7a2SStefano Zampini   PetscFunctionBegin;
30008122e43SStefano Zampini   if (!sub_schurs->use_mumps) {
30108122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
30208122e43SStefano Zampini   }
30308122e43SStefano Zampini 
30406a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
30506a4e24aSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adaptive selection not yet implemented for general matrix pencils (herm %d, posdef %d)\n",sub_schurs->is_hermitian,sub_schurs->is_posdef);
30606a4e24aSStefano Zampini   }
30706a4e24aSStefano Zampini 
308fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
309fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
310fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
311fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
312fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
313fd14bc51SStefano Zampini   }
314fd14bc51SStefano Zampini 
315e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
316e496cd5dSStefano 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);
317e496cd5dSStefano Zampini   }
318e496cd5dSStefano Zampini 
31908122e43SStefano Zampini   /* max size of subsets */
32008122e43SStefano Zampini   mss = 0;
32108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
32208122e43SStefano Zampini     PetscInt subset_size;
323862806e4SStefano Zampini 
32408122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
32508122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
32608122e43SStefano Zampini   }
32708122e43SStefano Zampini 
32808122e43SStefano Zampini   /* min/max and threshold */
32908122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
330f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
33108122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
332f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
333f6f667cfSStefano Zampini   if (nmin) {
334f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
335f6f667cfSStefano Zampini   }
33608122e43SStefano Zampini 
33708122e43SStefano Zampini   /* allocate lapack workspace */
33808122e43SStefano Zampini   cum = cum2 = 0;
33908122e43SStefano Zampini   maxneigs = 0;
34008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
34108122e43SStefano Zampini     PetscInt n,subset_size;
342f6f667cfSStefano Zampini 
34308122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
34408122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
3459162d606SStefano Zampini     cum += subset_size;
3469162d606SStefano Zampini     cum2 += subset_size*n;
34708122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
34808122e43SStefano Zampini   }
34908122e43SStefano Zampini   if (mss) {
3509ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
35108122e43SStefano Zampini       PetscBLASInt B_itype = 1;
35208122e43SStefano Zampini       PetscBLASInt B_N = mss;
3534c6709b3SStefano Zampini       PetscReal    zero = 0.0;
3544c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
35508122e43SStefano Zampini 
35608122e43SStefano Zampini       B_lwork = -1;
35708122e43SStefano Zampini       S = NULL;
35808122e43SStefano Zampini       St = NULL;
359a58a30b4SStefano Zampini       eigs = NULL;
360a58a30b4SStefano Zampini       eigv = NULL;
361a58a30b4SStefano Zampini       B_iwork = NULL;
362a58a30b4SStefano Zampini       B_ifail = NULL;
363d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
364d1710679SStefano Zampini       rwork = NULL;
365d1710679SStefano Zampini #endif
3668bec7fa6SStefano Zampini       thresh = 1.0;
36708122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
36808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
36908122e43SStefano 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));
37008122e43SStefano Zampini #else
37108122e43SStefano 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));
37208122e43SStefano Zampini #endif
37308122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
37408122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
37508122e43SStefano Zampini     } else {
37608122e43SStefano Zampini         /* TODO */
37708122e43SStefano Zampini     }
37808122e43SStefano Zampini   } else {
37908122e43SStefano Zampini     lwork = 0;
38008122e43SStefano Zampini   }
38108122e43SStefano Zampini 
38208122e43SStefano Zampini   nv = 0;
383d62866d3SStefano 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) */
384d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
38508122e43SStefano Zampini   }
3864c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
387f6f667cfSStefano Zampini   if (allocated_S_St) {
388f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
389f6f667cfSStefano Zampini   }
390f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
39108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
39208122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
39308122e43SStefano Zampini #endif
3949162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
3959162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
3969162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
39708122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
3989162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
39908122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
40008122e43SStefano Zampini 
40108122e43SStefano Zampini   maxneigs = 0;
40208122e43SStefano Zampini   cum = cum2 = cumarray = 0;
4039162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
4049162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
405d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
40608122e43SStefano Zampini     const PetscInt *idxs;
40708122e43SStefano Zampini 
408d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
40908122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
41008122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
41108122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
41208122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
4139162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
4149162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
41508122e43SStefano Zampini     }
41608122e43SStefano Zampini     cum2 = cum;
417d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
41808122e43SStefano Zampini   }
41908122e43SStefano Zampini 
42008122e43SStefano Zampini   if (mss) { /* multilevel */
42108122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
42208122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
42308122e43SStefano Zampini   }
42408122e43SStefano Zampini 
42508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
42608122e43SStefano Zampini 
42708122e43SStefano Zampini     const PetscInt *idxs;
428f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
429862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
43008122e43SStefano Zampini     PetscBLASInt   B_N;
431aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
43208122e43SStefano Zampini 
433862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
434f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
435f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
4369ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
437aff50787SStefano Zampini         PetscInt j,k;
438aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
439aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
440aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
44108122e43SStefano Zampini         }
44208122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
443aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
444aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
445aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
446aff50787SStefano Zampini           }
44708122e43SStefano Zampini         }
44808122e43SStefano Zampini       } else {
44908122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
45008122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
45108122e43SStefano Zampini       }
4528bec7fa6SStefano Zampini     } else {
453f6f667cfSStefano Zampini       S = Sarray + cumarray;
454f6f667cfSStefano Zampini       St = Starray + cumarray;
4558bec7fa6SStefano Zampini     }
45608122e43SStefano Zampini 
457f6f667cfSStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
458aff50787SStefano Zampini     /* see if we can save some work */
459aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
460aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
461aff50787SStefano Zampini     }
462aff50787SStefano Zampini 
463aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
464aff50787SStefano Zampini       B_neigs = 0;
465aff50787SStefano Zampini     } else {
466aff50787SStefano Zampini       /* Threshold: this is an heuristic for edges */
467f6f667cfSStefano Zampini       thresh = pcbddc->mat_graph->count[idxs[0]]*pcbddc->adaptive_threshold;
468f6f667cfSStefano Zampini 
4699ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
47008122e43SStefano Zampini         PetscBLASInt B_itype = 1;
471f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
4724c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
4739552c7c7SStefano Zampini         PetscInt     nmin_s;
47408122e43SStefano Zampini 
475fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
4768bec7fa6SStefano 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]]);
477fd14bc51SStefano Zampini         }
478d16cbb6bSStefano Zampini 
47908122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
480d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
481d16cbb6bSStefano Zampini 
482d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
48308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
484f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
48508122e43SStefano Zampini #else
486f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
48708122e43SStefano Zampini #endif
488d16cbb6bSStefano Zampini         } else {
489d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
490d16cbb6bSStefano Zampini           B_IL = 1;
491d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
492d16cbb6bSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
493d16cbb6bSStefano Zampini #else
494d16cbb6bSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
495d16cbb6bSStefano Zampini #endif
496d16cbb6bSStefano Zampini         }
49708122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
49808122e43SStefano Zampini         if (B_ierr) {
49908122e43SStefano Zampini           if (B_ierr < 0 ) {
50008122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
50108122e43SStefano Zampini           } else if (B_ierr <= B_N) {
50208122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
50308122e43SStefano Zampini           } else {
5049552c7c7SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1);
50508122e43SStefano Zampini           }
50608122e43SStefano Zampini         }
50708122e43SStefano Zampini 
50808122e43SStefano Zampini         if (B_neigs > nmax) {
509fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
510fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
511fd14bc51SStefano Zampini           }
512f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
51308122e43SStefano Zampini           B_neigs = nmax;
51408122e43SStefano Zampini         }
51508122e43SStefano Zampini 
5169552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
5179552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
51808122e43SStefano Zampini           PetscBLASInt B_neigs2;
51908122e43SStefano Zampini 
520f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
521f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
522fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
523fd14bc51SStefano 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);
524fd14bc51SStefano Zampini           }
5259ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
52608122e43SStefano Zampini             PetscInt j;
52708122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
52808122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
52908122e43SStefano Zampini             }
53008122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
53108122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
53208122e43SStefano Zampini             }
53308122e43SStefano Zampini           } else {
53408122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
53508122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
53608122e43SStefano Zampini           }
53708122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
53808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
539f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
54008122e43SStefano Zampini #else
541f6f667cfSStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
54208122e43SStefano Zampini #endif
54308122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
54408122e43SStefano Zampini           B_neigs += B_neigs2;
54508122e43SStefano Zampini         }
54608122e43SStefano Zampini         if (B_ierr) {
54708122e43SStefano Zampini           if (B_ierr < 0 ) {
54808122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
54908122e43SStefano Zampini           } else if (B_ierr <= B_N) {
55008122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
55108122e43SStefano Zampini           } else {
5529552c7c7SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1);
55308122e43SStefano Zampini           }
55408122e43SStefano Zampini         }
555fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
556ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
55708122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
55808122e43SStefano Zampini             if (eigs[j] == 0.0) {
559ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
56008122e43SStefano Zampini             } else {
561ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
562fd14bc51SStefano Zampini             }
56308122e43SStefano Zampini           }
56408122e43SStefano Zampini         }
56508122e43SStefano Zampini       } else {
56608122e43SStefano Zampini           /* TODO */
56708122e43SStefano Zampini       }
568aff50787SStefano Zampini     }
5698bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
5708bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
5719162d606SStefano Zampini     if (B_neigs) {
5729162d606SStefano 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);
573fd14bc51SStefano Zampini 
574fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
5759552c7c7SStefano Zampini         PetscInt ii;
5769552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
577ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
5789552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
579ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
580ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
581ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
582ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
583ac47001eSStefano Zampini #else
584ac47001eSStefano 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);
585ac47001eSStefano Zampini #endif
5869552c7c7SStefano Zampini           }
5879552c7c7SStefano Zampini         }
588fd14bc51SStefano Zampini       }
58908122e43SStefano Zampini #if 0
5909162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
59108122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
59208122e43SStefano Zampini         PetscScalar norm;
59308122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
5949162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
5959162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
59608122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
59708122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
59808122e43SStefano Zampini         } else {
59908122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
60008122e43SStefano Zampini         }
6019162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
602b1b3d7a2SStefano Zampini       }
603b1b3d7a2SStefano Zampini #endif
6049162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
6059162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
6069162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
6079162d606SStefano Zampini       cum++;
60808122e43SStefano Zampini     }
60908122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
61008122e43SStefano Zampini     /* shift for next computation */
61108122e43SStefano Zampini     cumarray += subset_size*subset_size;
61208122e43SStefano Zampini   }
613fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
614fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
615fd14bc51SStefano Zampini   }
61608122e43SStefano Zampini 
61708122e43SStefano Zampini   if (mss) {
61808122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
61908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
620f6f667cfSStefano Zampini     /* destroy matrices (junk) */
621f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
622f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
62308122e43SStefano Zampini   }
624f6f667cfSStefano Zampini   if (allocated_S_St) {
625f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
626f6f667cfSStefano Zampini   }
627f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
62808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
62908122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
63008122e43SStefano Zampini #endif
63108122e43SStefano Zampini   if (pcbddc->dbg_flag) {
6321b968477SStefano Zampini     PetscInt maxneigs_r;
63308122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
6349b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
63508122e43SStefano Zampini   }
63608122e43SStefano Zampini   PetscFunctionReturn(0);
63708122e43SStefano Zampini }
638b1b3d7a2SStefano Zampini 
639674ae819SStefano Zampini #undef __FUNCT__
640c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
641c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
642c8587f34SStefano Zampini {
643c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6448629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
645c8587f34SStefano Zampini   PetscErrorCode ierr;
646c8587f34SStefano Zampini 
647c8587f34SStefano Zampini   PetscFunctionBegin;
648f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
6495e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
650c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
651c8587f34SStefano Zampini 
652684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
6530fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
654684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
655c8587f34SStefano Zampini 
656c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
657b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
658c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
659c8587f34SStefano Zampini   }
660c8587f34SStefano Zampini 
6618629588bSStefano Zampini   /*
6628629588bSStefano Zampini      Setup local correction and local part of coarse basis.
6638629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
6648629588bSStefano Zampini   */
66547f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
6668629588bSStefano Zampini 
6678629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
6688629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
6698629588bSStefano Zampini 
6708629588bSStefano Zampini   /* free */
6718629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
672c8587f34SStefano Zampini   PetscFunctionReturn(0);
673c8587f34SStefano Zampini }
674c8587f34SStefano Zampini 
675c8587f34SStefano Zampini #undef __FUNCT__
676674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
677674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
678674ae819SStefano Zampini {
679674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
680674ae819SStefano Zampini   PetscErrorCode ierr;
681674ae819SStefano Zampini 
682674ae819SStefano Zampini   PetscFunctionBegin;
683674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
684674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
685674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
686674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
687785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
688674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
689f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
690f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
691785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
69263602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
69363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
694674ae819SStefano Zampini   PetscFunctionReturn(0);
695674ae819SStefano Zampini }
696674ae819SStefano Zampini 
697674ae819SStefano Zampini #undef __FUNCT__
698674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
699674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
700674ae819SStefano Zampini {
701674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
702674ae819SStefano Zampini   PetscErrorCode ierr;
703674ae819SStefano Zampini 
704674ae819SStefano Zampini   PetscFunctionBegin;
705b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
706674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
707674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
708674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
709b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
710674ae819SStefano Zampini   PetscFunctionReturn(0);
711674ae819SStefano Zampini }
712674ae819SStefano Zampini 
713674ae819SStefano Zampini #undef __FUNCT__
714674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
715674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
716674ae819SStefano Zampini {
717674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
71806656605SStefano Zampini   PetscScalar    *array;
719674ae819SStefano Zampini   PetscErrorCode ierr;
720674ae819SStefano Zampini 
721674ae819SStefano Zampini   PetscFunctionBegin;
722674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
72358da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
72406656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
72506656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
72658da7f69SStefano Zampini   }
727674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
728674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
72915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
73015aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
731674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
732674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
733674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
73406656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
735674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
736674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
7378ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
738674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
739674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
740674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
741f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
742f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
743f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
744f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
745727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
7460e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
747f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
74870cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7496e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
75081d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
7510369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
7528b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
7538b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
75481d14e9dSStefano Zampini   ierr = PetscFree2(pcbddc->B0_cols,pcbddc->B0_vals);CHKERRQ(ierr);
755674ae819SStefano Zampini   PetscFunctionReturn(0);
756674ae819SStefano Zampini }
757674ae819SStefano Zampini 
758674ae819SStefano Zampini #undef __FUNCT__
759f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
760f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
7616bfb1811SStefano Zampini {
7626bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
7636bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
7646bfb1811SStefano Zampini   VecType        impVecType;
765019a44ceSStefano Zampini   PetscInt       n_constraints,n_R,old_size,n_benign;
7666bfb1811SStefano Zampini   PetscErrorCode ierr;
7676bfb1811SStefano Zampini 
7686bfb1811SStefano Zampini   PetscFunctionBegin;
769f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
770019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
771f4ddd8eeSStefano Zampini   }
772e7b262bdSStefano Zampini   /* get sizes */
773c9ed8603SStefano Zampini   n_benign = 0;
774c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) n_benign = 1;
775019a44ceSStefano Zampini   n_constraints = pcbddc->local_primal_size - n_benign - pcbddc->n_vertices;
776b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
7776bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
778e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
779e7b262bdSStefano Zampini   /* R nodes */
780e7b262bdSStefano Zampini   old_size = -1;
781e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
782e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
783e7b262bdSStefano Zampini   }
784e7b262bdSStefano Zampini   if (n_R != old_size) {
785e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
786e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
7876bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
7886bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
7896bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
7906bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
791e7b262bdSStefano Zampini   }
792e7b262bdSStefano Zampini   /* local primal dofs */
793e7b262bdSStefano Zampini   old_size = -1;
794e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
795e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
796e7b262bdSStefano Zampini   }
797e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
798e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
79983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
800e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
8016bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
802e7b262bdSStefano Zampini   }
803e7b262bdSStefano Zampini   /* local explicit constraints */
804e7b262bdSStefano Zampini   old_size = -1;
805e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
806e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
807e7b262bdSStefano Zampini   }
808e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
809e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
81083b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
81183b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
81283b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
81383b7ccabSStefano Zampini   }
8146bfb1811SStefano Zampini   PetscFunctionReturn(0);
8156bfb1811SStefano Zampini }
8166bfb1811SStefano Zampini 
8176bfb1811SStefano Zampini #undef __FUNCT__
81847f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
81947f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
82088ebb749SStefano Zampini {
82125084f0cSStefano Zampini   PetscErrorCode  ierr;
82225084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
82388ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
82488ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
825d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
82625084f0cSStefano Zampini   /* submatrices of local problem */
82780677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
828019a44ceSStefano Zampini   /* submatrices of benign trick */
829d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
83006656605SStefano Zampini   /* submatrices of local coarse problem */
83106656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
83225084f0cSStefano Zampini   /* working matrices */
83306656605SStefano Zampini   Mat             C_CR;
83425084f0cSStefano Zampini   /* additional working stuff */
83506656605SStefano Zampini   PC              pc_R;
836d12edf2fSStefano Zampini   Mat             F,B0 = NULL;
83706656605SStefano Zampini   PetscBool       isLU,isCHOL,isILU;
83806656605SStefano Zampini 
83925084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
84006656605SStefano Zampini   PetscScalar     *work;
84106656605SStefano Zampini   PetscInt        *idx_V_B;
842d12edf2fSStefano Zampini   PetscInt        n,n_vertices,n_constraints,n_benign,p0_lidx_I = 0;
84306656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
844b9d89cd5SStefano Zampini   PetscBool       unsymmetric_check;
84545a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
84688ebb749SStefano Zampini   MatType         impMatType;
84725084f0cSStefano Zampini   /* some shortcuts to scalars */
84806656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
84988ebb749SStefano Zampini 
85088ebb749SStefano Zampini   PetscFunctionBegin;
851c9ed8603SStefano Zampini   n_benign = 0;
852c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) n_benign = 1;
853b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
854019a44ceSStefano Zampini   n_constraints = pcbddc->local_primal_size - n_benign - n_vertices;
85588ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
856b371cd4fSStefano Zampini   n_B = pcis->n_B;
857b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
85888ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
85988ebb749SStefano Zampini 
86088ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
86188ebb749SStefano Zampini   impMatType = MATSEQDENSE;
86288ebb749SStefano Zampini 
86388ebb749SStefano Zampini   /* vertices in boundary numbering */
864785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
8650e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
86688ebb749SStefano Zampini   if (i != n_vertices) {
86722d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
86888ebb749SStefano Zampini   }
86988ebb749SStefano Zampini 
87006656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
871019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
87206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
87306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
87406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
87506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
87606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
87706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
87806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
87906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
88006656605SStefano Zampini 
88106656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
88206656605SStefano Zampini   /* allocate workspace */
88306656605SStefano Zampini   n = 0;
88406656605SStefano Zampini   if (n_constraints) {
88506656605SStefano Zampini     n += n_R*n_constraints;
88606656605SStefano Zampini   }
88706656605SStefano Zampini   if (n_vertices) {
88806656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
88980677318SStefano Zampini     n = PetscMax((n_R+n_B)*n_vertices,n);
89006656605SStefano Zampini   }
8913301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
89206656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
89306656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
89406656605SStefano Zampini   }
89506656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
89606656605SStefano Zampini 
89706656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
89806656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
89906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
90006656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
90106656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
90206656605SStefano Zampini   if (isLU || isILU || isCHOL) {
90306656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
904d62866d3SStefano Zampini   } else if (sub_schurs->reuse_mumps) {
905d62866d3SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
906d62866d3SStefano Zampini     MatFactorType type;
907d62866d3SStefano Zampini 
9086816873aSStefano Zampini     F = reuse_mumps->F;
9096816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
910d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
91106656605SStefano Zampini   } else {
91206656605SStefano Zampini     F = NULL;
91306656605SStefano Zampini   }
91406656605SStefano Zampini 
91588ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
91688ebb749SStefano Zampini   if (n_constraints) {
91706656605SStefano Zampini     Mat         M1,M2,M3;
91880677318SStefano Zampini     Mat         auxmat;
91906656605SStefano Zampini     IS          is_aux;
92080677318SStefano Zampini     PetscScalar *array,*array2;
92106656605SStefano Zampini 
922f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
92380677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
92488ebb749SStefano Zampini 
92525084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
92625084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
9278ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
92880677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
92988ebb749SStefano Zampini 
93080677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
93180677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
93206656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
93388ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
93406656605SStefano Zampini       const PetscScalar *row_cmat_values;
93506656605SStefano Zampini       const PetscInt    *row_cmat_indices;
93606656605SStefano Zampini       PetscInt          size_of_constraint,j;
93788ebb749SStefano Zampini 
93806656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
93906656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
94006656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
94106656605SStefano Zampini       }
94206656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
94306656605SStefano Zampini     }
94480677318SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
94506656605SStefano Zampini     if (F) {
94606656605SStefano Zampini       Mat B;
94706656605SStefano Zampini 
94806656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
94980677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
95006656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
95106656605SStefano Zampini     } else {
95280677318SStefano Zampini       PetscScalar *marr;
95380677318SStefano Zampini 
95480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
95506656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
95606656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
95780677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*n_R);CHKERRQ(ierr);
95806656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
95906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
96006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
96106656605SStefano Zampini       }
96280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
96306656605SStefano Zampini     }
96480677318SStefano Zampini     if (!pcbddc->switch_static) {
96580677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
96680677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
96780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
96880677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
96980677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*n_R);CHKERRQ(ierr);
97080677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
97180677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
97280677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
97380677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
97480677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
97580677318SStefano Zampini       }
97680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
97780677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
97880677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
97980677318SStefano Zampini     } else {
98080677318SStefano Zampini       ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
98180677318SStefano Zampini       pcbddc->local_auxmat2 = local_auxmat2_R;
98225084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
98380677318SStefano Zampini     }
98480677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
98580677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
98680677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
98706656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
98806656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
98980677318SStefano Zampini     if (isCHOL) {
99080677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
99180677318SStefano Zampini     } else {
99225084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
99380677318SStefano Zampini     }
99480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
99506656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
99625084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
99725084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
99825084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
99980677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
100080677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
100180677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
100206656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
100306656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1004f4ddd8eeSStefano Zampini   }
100588ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
1006d16cbb6bSStefano Zampini   if (n_benign) {
1007d16cbb6bSStefano Zampini     IS        dummy;
1008d16cbb6bSStefano Zampini     Mat       B0_R;
1009d16cbb6bSStefano Zampini     PetscReal norm;
1010d16cbb6bSStefano Zampini     PetscInt  ii[2];
1011d16cbb6bSStefano Zampini 
1012d16cbb6bSStefano Zampini     ii[0] = 0;
1013d16cbb6bSStefano Zampini     ii[1] = pcbddc->B0_ncol;
1014d16cbb6bSStefano Zampini     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,1,pcis->n,ii,pcbddc->B0_cols,pcbddc->B0_vals,&B0);CHKERRQ(ierr);
1015d16cbb6bSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&dummy);CHKERRQ(ierr);
1016d16cbb6bSStefano Zampini     ierr = MatGetSubMatrix(B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
1017d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
1018d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
1019d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
1020d16cbb6bSStefano Zampini     }
1021d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
1022d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1023d16cbb6bSStefano Zampini   }
1024d16cbb6bSStefano Zampini 
102588ebb749SStefano Zampini   if (n_vertices) {
102606656605SStefano Zampini     IS is_aux;
10273a50541eSStefano Zampini 
10286816873aSStefano Zampini     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
10296816873aSStefano Zampini       IS tis;
10306816873aSStefano Zampini 
10316816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
10326816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
10336816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
10346816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
10356816873aSStefano Zampini     } else {
10363a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
10376816873aSStefano Zampini     }
10389577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
10399577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
104004708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
1041019a44ceSStefano Zampini     if (n_benign) {
1042019a44ceSStefano Zampini       IS dummy;
1043019a44ceSStefano Zampini 
1044019a44ceSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&dummy);CHKERRQ(ierr);
1045019a44ceSStefano Zampini       ierr = MatGetSubMatrix(B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1046019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1047019a44ceSStefano Zampini     }
104825084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
104988ebb749SStefano Zampini   }
105088ebb749SStefano Zampini 
105188ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1052f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
105306656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
105406656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
105506656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
105606656605SStefano Zampini     }
1057f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
105806656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
105906656605SStefano Zampini       PetscScalar *marray;
106006656605SStefano Zampini 
106106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
106206656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1063f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1064f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1065f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1066f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1067f4ddd8eeSStefano Zampini     }
1068f4ddd8eeSStefano Zampini   }
106906656605SStefano Zampini 
1070f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
107106656605SStefano Zampini     PetscScalar *marray;
107288ebb749SStefano Zampini 
107306656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
10748eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
107506656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
107688ebb749SStefano Zampini     }
10773301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
107806656605SStefano Zampini       n *= 2;
107988ebb749SStefano Zampini     }
108006656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
108106656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
108206656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
10838eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
108406656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
108506656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
108688ebb749SStefano Zampini     }
10873301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
108806656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
10898eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
109006656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
109106656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
109288ebb749SStefano Zampini       }
109388ebb749SStefano Zampini     } else {
1094c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1095c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
10961b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1097c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1098c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1099c0553b1fSStefano Zampini       }
110088ebb749SStefano Zampini     }
110106656605SStefano Zampini   }
1102019a44ceSStefano Zampini 
110306656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
1104d12edf2fSStefano Zampini   if (n_benign && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1105d12edf2fSStefano Zampini     const PetscInt *idxs;
1106d12edf2fSStefano Zampini 
1107d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1108d12edf2fSStefano Zampini     ierr = PetscFindInt(pcbddc->benign_p0_lidx,pcis->n-pcis->n_B,idxs,&p0_lidx_I);CHKERRQ(ierr);
1109d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1110d12edf2fSStefano Zampini   }
1111d16cbb6bSStefano Zampini 
111206656605SStefano Zampini   /* vertices */
111306656605SStefano Zampini   if (n_vertices) {
111416f15bc4SStefano Zampini 
111504708bb6SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
111604708bb6SStefano Zampini 
111716f15bc4SStefano Zampini     if (n_R) {
111806656605SStefano Zampini       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
111906656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
112016f15bc4SStefano Zampini       PetscScalar  *x,*y;
112104708bb6SStefano Zampini       PetscBool    isseqaij;
112206656605SStefano Zampini 
112321eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
112406656605SStefano Zampini       ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
112504708bb6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
11266816873aSStefano Zampini       if (F) { /* TODO could be optimized for symmetric problems */
112706656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
112806656605SStefano Zampini       } else {
112906656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
113006656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
113106656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
113206656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
113306656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
113406656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
113506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
113606656605SStefano Zampini         }
113706656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
113806656605SStefano Zampini       }
113980677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
114006656605SStefano Zampini       /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
114106656605SStefano Zampini       if (n_constraints) {
114206656605SStefano Zampini         Mat B;
114380677318SStefano Zampini 
1144b3d85658SStefano Zampini         ierr = PetscMemzero(work+n_R*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
114580677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
114680677318SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
114780677318SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+n_R*n_vertices+i*n_B);CHKERRQ(ierr);
114880677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
114980677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
115080677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
115180677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
115280677318SStefano Zampini         }
115380677318SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
115480677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
115580677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
115606656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
115780677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
115806656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
115906656605SStefano Zampini         ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
116006656605SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
116106656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
116206656605SStefano Zampini       }
116304708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
116404708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
116504708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
116604708bb6SStefano Zampini       }
116706656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
116880677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
116906656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
117006656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
117106656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
117206656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
117306656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
117406656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
117506656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1176d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1177019a44ceSStefano Zampini     } else {
1178d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1179d16cbb6bSStefano Zampini     }
1180d16cbb6bSStefano Zampini     if (n_benign) {
1181019a44ceSStefano Zampini       const PetscScalar *vals;
1182019a44ceSStefano Zampini       const PetscInt    *idxs;
1183019a44ceSStefano Zampini       PetscInt          n,j;
1184019a44ceSStefano Zampini 
1185019a44ceSStefano Zampini       ierr = MatGetRow(B0_V,0,&n,&idxs,&vals);CHKERRQ(ierr);
1186d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
1187d16cbb6bSStefano Zampini         coarse_submat_vals[(pcbddc->local_primal_size-1)*pcbddc->local_primal_size+idxs[j]] = vals[j];
1188d16cbb6bSStefano Zampini         coarse_submat_vals[(idxs[j]+1)*pcbddc->local_primal_size-1] = vals[j];
1189019a44ceSStefano Zampini       }
1190019a44ceSStefano Zampini       ierr = MatRestoreRow(B0_V,0,&n,&idxs,&vals);CHKERRQ(ierr);
119116f15bc4SStefano Zampini     }
119221eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1193d16cbb6bSStefano Zampini 
119406656605SStefano Zampini     /* coarse basis functions */
119506656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
119616f15bc4SStefano Zampini       PetscScalar *y;
119716f15bc4SStefano Zampini 
119806656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
119906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
120006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
120106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
120206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
120306656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
120406656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
120506656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
120606656605SStefano Zampini 
120706656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
120806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
120906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
121006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
121106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
121206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1213a0aff763SStefano Zampini         if (n_benign) y[n_D*i+p0_lidx_I] = 0.0;
121406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
121506656605SStefano Zampini       }
121606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
121706656605SStefano Zampini     }
121804708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
121904708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
122006656605SStefano Zampini   }
122106656605SStefano Zampini 
122206656605SStefano Zampini   if (n_constraints) {
122306656605SStefano Zampini     Mat B;
122406656605SStefano Zampini 
122506656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
122606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
122780677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
122806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
122906656605SStefano Zampini     if (n_vertices) {
123080677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
123180677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
123280677318SStefano Zampini       } else {
123380677318SStefano Zampini         Mat S_VCt;
123480677318SStefano Zampini 
123580677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
123680677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
123780677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
123880677318SStefano Zampini       }
123906656605SStefano Zampini     }
124006656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
124106656605SStefano Zampini     /* coarse basis functions */
124206656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
124306656605SStefano Zampini       PetscScalar *y;
124406656605SStefano Zampini 
124506656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
124606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
124706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
124806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
124906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
125006656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
125106656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
125206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
125306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
125406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
125506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
125606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
125706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1258d16cbb6bSStefano Zampini         if (n_benign) y[n_D*(i+n_vertices)+p0_lidx_I] = 0.0;
125906656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
126006656605SStefano Zampini       }
126106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
126206656605SStefano Zampini     }
126306656605SStefano Zampini   }
126480677318SStefano Zampini   if (n_constraints) {
126580677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
126680677318SStefano Zampini   }
126706656605SStefano Zampini 
1268019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1269019a44ceSStefano Zampini 
127006656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
12713301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
127206656605SStefano Zampini 
127306656605SStefano Zampini     if (n_constraints) {
127416f15bc4SStefano Zampini       Mat S_CCT,B_C;
127506656605SStefano Zampini 
127680677318SStefano Zampini       /* this is a lazy thing */
127780677318SStefano Zampini       ierr = MatConvert(C_CR,impMatType,MAT_REUSE_MATRIX,&C_CR);CHKERRQ(ierr);
127806656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
127906656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
128006656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
128116f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
128206656605SStefano Zampini       if (n_vertices) {
128316f15bc4SStefano Zampini         Mat B_V,S_VCT;
128406656605SStefano Zampini 
128506656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
128606656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
128706656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
128806656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
128916f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
129006656605SStefano Zampini       }
129106656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
129280677318SStefano Zampini     } else { /* if there are no constraints, reset work */
129380677318SStefano Zampini       ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
129406656605SStefano Zampini     }
129516f15bc4SStefano Zampini     if (n_vertices && n_R) {
129606656605SStefano Zampini       Mat          A_VRT;
129780677318SStefano Zampini       PetscScalar  *marray;
129806656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
129906656605SStefano Zampini 
130080677318SStefano Zampini       ierr = MatTranspose(A_VR,MAT_INITIAL_MATRIX,&A_VRT);CHKERRQ(ierr);
130180677318SStefano Zampini       ierr = MatConvert(A_VRT,impMatType,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
130280677318SStefano Zampini       ierr = MatDenseGetArray(A_VRT,&marray);CHKERRQ(ierr);
130306656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
130480677318SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,marray,&B_one,work,&B_one));
130580677318SStefano Zampini       ierr = MatDenseRestoreArray(A_VRT,&marray);CHKERRQ(ierr);
130616f15bc4SStefano Zampini       ierr = MatDestroy(&A_VRT);CHKERRQ(ierr);
130706656605SStefano Zampini     }
130806656605SStefano Zampini 
130906656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
131006656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
131106656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
131206656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
131306656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
131406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
131506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
131606656605SStefano Zampini       }
131706656605SStefano Zampini     } else {
131806656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
131906656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
132006656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
132106656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
132206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
132306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
132406656605SStefano Zampini       }
132506656605SStefano Zampini     }
132606656605SStefano Zampini     /* coarse basis functions */
132706656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
132806656605SStefano Zampini       PetscScalar *y;
132906656605SStefano Zampini 
133006656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
133106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
133206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
133306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
133406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
133506656605SStefano Zampini       if (i<n_vertices) {
133606656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
133706656605SStefano Zampini       }
133806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
133906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
134006656605SStefano Zampini 
134106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
134206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
134306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
134406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
134506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
134606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
134706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
134806656605SStefano Zampini       }
134906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
135006656605SStefano Zampini     }
135106656605SStefano Zampini   }
1352d62866d3SStefano Zampini   /* free memory */
135388ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
135406656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
135506656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
135606656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
135706656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
1358d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
1359d62866d3SStefano Zampini   if (n_vertices) {
1360d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1361d62866d3SStefano Zampini   }
1362d62866d3SStefano Zampini   if (n_constraints) {
1363d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1364d62866d3SStefano Zampini   }
136588ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
136688ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
136788ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1368d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
136988ebb749SStefano Zampini     Mat         coarse_sub_mat;
137025084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
137188ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
137288ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
137388ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
13748bec7fa6SStefano Zampini     Mat         C_B,CPHI;
13758bec7fa6SStefano Zampini     IS          is_dummy;
13768bec7fa6SStefano Zampini     Vec         mones;
137788ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
137888ebb749SStefano Zampini     PetscReal   real_value;
137988ebb749SStefano Zampini 
138088ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
138188ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
138288ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
138388ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
138488ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
138588ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1386c0553b1fSStefano Zampini     if (unsymmetric_check) {
138788ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
138888ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
138988ebb749SStefano Zampini     }
139088ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
139188ebb749SStefano Zampini 
139225084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
13933301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
139425084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1395c0553b1fSStefano Zampini     if (unsymmetric_check) {
139688ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
139788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
139888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
139988ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
140088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
140188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
140288ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
140388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
140488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
140588ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
140688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
140788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
140888ebb749SStefano Zampini     } else {
140988ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
141088ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
141188ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
141288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
141388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
141488ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
141588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
141688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
141788ebb749SStefano Zampini     }
141888ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
141988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
142088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
142188ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
1422d12edf2fSStefano Zampini     if (n_benign) {
1423d12edf2fSStefano Zampini       Mat B0_I,B0_B,B0_BPHI,B0_IPHI;
1424d12edf2fSStefano Zampini       PetscScalar *data,*data2;
1425d12edf2fSStefano Zampini 
1426d12edf2fSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&is_dummy);CHKERRQ(ierr);
1427d12edf2fSStefano Zampini       ierr = MatGetSubMatrix(B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
1428d12edf2fSStefano Zampini       ierr = MatGetSubMatrix(B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
1429d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
1430d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
1431d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
1432d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
1433d12edf2fSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
1434d16cbb6bSStefano Zampini         data[(pcbddc->local_primal_size-1)*pcbddc->local_primal_size+i] += data2[i];
1435d16cbb6bSStefano Zampini         data[(i+1)*pcbddc->local_primal_size-1] += data2[i];
1436d12edf2fSStefano Zampini       }
1437d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
1438d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
1439d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
1440d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1441d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
1442d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
1443d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
1444d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1445d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
1446d12edf2fSStefano Zampini     }
1447d12edf2fSStefano Zampini #if 0
1448d12edf2fSStefano Zampini   {
1449d12edf2fSStefano Zampini     PetscViewer viewer;
1450d12edf2fSStefano Zampini     char filename[256];
1451d12edf2fSStefano Zampini     sprintf(filename,"proj_local_coarse_mat%d.m",PetscGlobalRank);
1452d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1453d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1454d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
1455d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1456d12edf2fSStefano Zampini   }
1457d12edf2fSStefano Zampini #endif
145881d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
14598bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
14600fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
146106656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
14628bec7fa6SStefano Zampini 
14638bec7fa6SStefano Zampini     /* check constraints */
1464d12edf2fSStefano Zampini     if (!n_benign) {
14658bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
14668bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
14678bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
14688bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
14698bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
14708bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
14718bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1472bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1473c0553b1fSStefano Zampini       if (unsymmetric_check) {
1474bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1475bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1476bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1477bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1478bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
147988ebb749SStefano Zampini       }
14808bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
14818bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
14828bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
14838bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
1484d12edf2fSStefano Zampini     }
148525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
148688ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
148788ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
148888ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
148988ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
149088ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
149188ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
149288ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
149388ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
149488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
149588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1496c0553b1fSStefano Zampini     if (unsymmetric_check) {
149788ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
149888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
149988ebb749SStefano Zampini     }
150088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
150188ebb749SStefano Zampini   }
1502d12edf2fSStefano Zampini   ierr = MatDestroy(&B0);CHKERRQ(ierr);
15038629588bSStefano Zampini   /* get back data */
15048629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
150588ebb749SStefano Zampini   PetscFunctionReturn(0);
150688ebb749SStefano Zampini }
150788ebb749SStefano Zampini 
150888ebb749SStefano Zampini #undef __FUNCT__
1509d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1510d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
1511aa0d41d4SStefano Zampini {
1512d65f70fdSStefano Zampini   Mat            *work_mat;
1513d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1514d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1515d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1516aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1517aa0d41d4SStefano Zampini 
1518aa0d41d4SStefano Zampini   PetscFunctionBegin;
1519d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1520d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1521d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1522d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1523aa0d41d4SStefano Zampini 
1524d65f70fdSStefano Zampini   if (!rsorted) {
1525906d46d4SStefano Zampini     const PetscInt *idxs;
1526906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
1527aa0d41d4SStefano Zampini 
1528d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1529d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1530d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1531d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1532aa0d41d4SStefano Zampini     }
1533d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1534d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1535d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1536d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1537aa0d41d4SStefano Zampini     }
1538d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1539d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1540d65f70fdSStefano Zampini   } else {
1541d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1542d65f70fdSStefano Zampini     isrow_s = isrow;
1543aa0d41d4SStefano Zampini   }
1544906d46d4SStefano Zampini 
1545d65f70fdSStefano Zampini   if (!csorted) {
1546d65f70fdSStefano Zampini     if (isrow == iscol) {
1547d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1548d65f70fdSStefano Zampini       iscol_s = isrow_s;
1549d65f70fdSStefano Zampini     } else {
1550d65f70fdSStefano Zampini       const PetscInt *idxs;
1551d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1552906d46d4SStefano Zampini 
1553d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1554d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1555d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1556d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1557d65f70fdSStefano Zampini       }
1558d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1559d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1560d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1561d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1562d65f70fdSStefano Zampini       }
1563d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1564d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1565d65f70fdSStefano Zampini     }
1566d65f70fdSStefano Zampini   } else {
1567d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1568d65f70fdSStefano Zampini     iscol_s = iscol;
1569d65f70fdSStefano Zampini   }
1570d65f70fdSStefano Zampini 
1571d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1572d65f70fdSStefano Zampini 
1573d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1574906d46d4SStefano Zampini     Mat      new_mat;
1575d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1576906d46d4SStefano Zampini 
1577d65f70fdSStefano Zampini     if (!rsorted) {
1578d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1579d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1580d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1581d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1582906d46d4SStefano Zampini       }
1583d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1584d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1585d65f70fdSStefano Zampini     } else {
1586d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1587906d46d4SStefano Zampini     }
1588d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1589d65f70fdSStefano Zampini 
1590d65f70fdSStefano Zampini     if (!csorted) {
1591d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1592d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1593d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1594d65f70fdSStefano Zampini       } else {
1595d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1596d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1597d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1598d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1599d65f70fdSStefano Zampini         }
1600d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1601d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1602d65f70fdSStefano Zampini       }
1603d65f70fdSStefano Zampini     } else {
1604d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1605d65f70fdSStefano Zampini     }
1606d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1607d65f70fdSStefano Zampini 
1608d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1609d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1610d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1611d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1612d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1613d65f70fdSStefano Zampini   }
1614d65f70fdSStefano Zampini 
1615d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1616d65f70fdSStefano Zampini   *B = work_mat[0];
1617d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1618d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1619d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1620d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1621d65f70fdSStefano Zampini }
1622d65f70fdSStefano Zampini 
1623d65f70fdSStefano Zampini #undef __FUNCT__
16245e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
16255e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1626aa0d41d4SStefano Zampini {
1627aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
16285e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1629d65f70fdSStefano Zampini   Mat            new_mat;
16305e8657edSStefano Zampini   IS             is_local,is_global;
1631d65f70fdSStefano Zampini   PetscInt       local_size;
1632d65f70fdSStefano Zampini   PetscBool      isseqaij;
1633aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1634aa0d41d4SStefano Zampini 
1635aa0d41d4SStefano Zampini   PetscFunctionBegin;
1636aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16375e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
16385e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1639b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
1640aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1641d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
1642aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1643906d46d4SStefano Zampini 
1644906d46d4SStefano Zampini   /* check */
1645906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
1646906d46d4SStefano Zampini     Vec       x,x_change;
1647906d46d4SStefano Zampini     PetscReal error;
1648906d46d4SStefano Zampini 
16495e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1650906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
16515e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
1652e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1653e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1654d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
1655e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1656e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1657906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1658906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1659906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1660906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1661906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
1662906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1663906d46d4SStefano Zampini   }
1664906d46d4SStefano Zampini 
166522d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
16669b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
166722d5777bSStefano Zampini   if (isseqaij) {
1668d65f70fdSStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1669aa0d41d4SStefano Zampini   } else {
1670aa0d41d4SStefano Zampini     Mat work_mat;
1671aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1672d65f70fdSStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1673aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
1674aa0d41d4SStefano Zampini   }
16753301b35fSStefano Zampini   if (matis->A->symmetric_set) {
16763301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
1677e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
16783301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
1679e496cd5dSStefano Zampini #endif
16803301b35fSStefano Zampini   }
168145a1bb75SStefano Zampini   /*
168245a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1683d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
168445a1bb75SStefano Zampini   */
1685d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
1686aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
1687aa0d41d4SStefano Zampini }
1688aa0d41d4SStefano Zampini 
1689aa0d41d4SStefano Zampini #undef __FUNCT__
1690a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
16918ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
1692a64d13efSStefano Zampini {
1693a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
1694a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1695d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
169653892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
16973a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
16983a50541eSStefano Zampini   PetscInt        vbs,bs;
16996816873aSStefano Zampini   PetscBT         bitmask=NULL;
1700a64d13efSStefano Zampini   PetscErrorCode  ierr;
1701a64d13efSStefano Zampini 
1702a64d13efSStefano Zampini   PetscFunctionBegin;
1703b23d619eSStefano Zampini   /*
1704b23d619eSStefano Zampini     No need to setup local scatters if
1705b23d619eSStefano Zampini       - primal space is unchanged
1706b23d619eSStefano Zampini         AND
1707b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
1708b23d619eSStefano Zampini         AND
1709b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
1710b23d619eSStefano Zampini   */
1711b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
1712f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
1713f4ddd8eeSStefano Zampini   }
1714f4ddd8eeSStefano Zampini   /* destroy old objects */
1715f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1716f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1717f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1718a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
1719b371cd4fSStefano Zampini   n_B = pcis->n_B;
1720b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
1721b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
17223a50541eSStefano Zampini 
1723a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
17246816873aSStefano Zampini 
172553892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
17266816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
1727854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
1728a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
1729a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
17300e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
1731a64d13efSStefano Zampini     }
1732a64d13efSStefano Zampini 
1733a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
17344641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
17356816873aSStefano Zampini         idx_R_local[n_R++] = i;
1736a64d13efSStefano Zampini       }
1737a64d13efSStefano Zampini     }
173853892102SStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
17396816873aSStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
17406816873aSStefano Zampini 
174153892102SStefano Zampini     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
174253892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
17436816873aSStefano Zampini   }
17443a50541eSStefano Zampini 
17453a50541eSStefano Zampini   /* Block code */
17463a50541eSStefano Zampini   vbs = 1;
17473a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
17483a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
17493a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
17503a50541eSStefano Zampini     PetscInt  *vary;
1751d3df7717SStefano Zampini     if (!sub_schurs->reuse_mumps) {
1752785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
17533a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
1754d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
1755d3df7717SStefano 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 */
17560e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
1757d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
17583a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
17593a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
17603a50541eSStefano Zampini           break;
17613a50541eSStefano Zampini         }
17623a50541eSStefano Zampini       }
1763d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
1764d3df7717SStefano Zampini     } else {
1765d3df7717SStefano Zampini       /* Verify directly the R set */
1766d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
1767d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
1768d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
1769d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
1770d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
1771d3df7717SStefano Zampini             break;
1772d3df7717SStefano Zampini           }
1773d3df7717SStefano Zampini         }
1774d3df7717SStefano Zampini       }
1775d3df7717SStefano Zampini     }
17763a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
17773a50541eSStefano Zampini       vbs = bs;
17783a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
17793a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
17803a50541eSStefano Zampini       }
17813a50541eSStefano Zampini     }
17823a50541eSStefano Zampini   }
17833a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
178453892102SStefano Zampini   if (sub_schurs->reuse_mumps) {
178553892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
178653892102SStefano Zampini 
178753892102SStefano Zampini     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
178853892102SStefano Zampini     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
178953892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
179053892102SStefano Zampini     reuse_mumps->is_R = pcbddc->is_R_local;
179153892102SStefano Zampini   } else {
17923a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
179353892102SStefano Zampini   }
1794a64d13efSStefano Zampini 
1795a64d13efSStefano Zampini   /* print some info if requested */
1796a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
1797c9ed8603SStefano Zampini     PetscInt benign = 0;
1798019a44ceSStefano Zampini 
1799c9ed8603SStefano Zampini     if (pcbddc->benign_p0_lidx >= 0) benign = 1;
1800a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1801a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
18020fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1803a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1804a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
1805019a44ceSStefano 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-benign,pcbddc->local_primal_size);CHKERRQ(ierr);
1806a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1807a64d13efSStefano Zampini   }
1808a64d13efSStefano Zampini 
1809a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
18106816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
18116816873aSStefano Zampini     IS       is_aux1,is_aux2;
18126816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
18136816873aSStefano Zampini 
18143a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1815854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
1816854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
1817a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
18184641a718SStefano Zampini     for (i=0; i<n_D; i++) {
18194641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
18204641a718SStefano Zampini     }
1821a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1822a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
18234641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
18244641a718SStefano Zampini         aux_array1[j++] = i;
1825a64d13efSStefano Zampini       }
1826a64d13efSStefano Zampini     }
1827a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1828a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1829a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
18304641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
18314641a718SStefano Zampini         aux_array2[j++] = i;
1832a64d13efSStefano Zampini       }
1833a64d13efSStefano Zampini     }
1834a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1835a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
1836a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1837a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1838a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1839a64d13efSStefano Zampini 
18408eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
1841785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
1842a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
18434641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
18444641a718SStefano Zampini           aux_array1[j++] = i;
1845a64d13efSStefano Zampini         }
1846a64d13efSStefano Zampini       }
1847a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1848a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1849a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1850a64d13efSStefano Zampini     }
18514641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
18523a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1853d62866d3SStefano Zampini   } else {
185453892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
18556816873aSStefano Zampini     IS               tis;
18566816873aSStefano Zampini     PetscInt         schur_size;
18576816873aSStefano Zampini 
185853892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
18596816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
186053892102SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
18616816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
18626816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
18636816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
18646816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
18656816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
1866d62866d3SStefano Zampini     }
1867d62866d3SStefano Zampini   }
1868a64d13efSStefano Zampini   PetscFunctionReturn(0);
1869a64d13efSStefano Zampini }
1870a64d13efSStefano Zampini 
1871304d26faSStefano Zampini 
1872304d26faSStefano Zampini #undef __FUNCT__
1873304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1874684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1875304d26faSStefano Zampini {
1876304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1877304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1878304d26faSStefano Zampini   PC             pc_temp;
1879304d26faSStefano Zampini   Mat            A_RR;
1880f4ddd8eeSStefano Zampini   MatReuse       reuse;
1881304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1882304d26faSStefano Zampini   PetscReal      value;
188304708bb6SStefano Zampini   PetscInt       n_D,n_R;
18849577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1885304d26faSStefano Zampini   PetscErrorCode ierr;
1886e604994aSStefano Zampini   /* prefixes stuff */
1887312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1888e604994aSStefano Zampini   size_t         len;
1889304d26faSStefano Zampini 
1890304d26faSStefano Zampini   PetscFunctionBegin;
1891304d26faSStefano Zampini 
1892e604994aSStefano Zampini   /* compute prefixes */
1893e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1894e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1895e604994aSStefano Zampini   if (!pcbddc->current_level) {
1896e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1897e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1898e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1899e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1900e604994aSStefano Zampini   } else {
1901e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1902312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1903e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1904e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1905312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1906312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
190734d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
190834d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1909e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1910e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1911e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1912e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1913e604994aSStefano Zampini   }
1914e604994aSStefano Zampini 
1915304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1916684f6988SStefano Zampini   if (dirichlet) {
1917d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
19183301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
19193301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
1920964fefecSStefano Zampini     }
1921ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
1922964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
1923304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1924304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1925304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1926304d26faSStefano Zampini       /* default */
1927304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1928e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
19299577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1930304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
19319577ea80SStefano Zampini       if (issbaij) {
19329577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
19339577ea80SStefano Zampini       } else {
1934304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
19359577ea80SStefano Zampini       }
1936304d26faSStefano Zampini       /* Allow user's customization */
1937304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1938304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1939304d26faSStefano Zampini     }
1940d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1941d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
1942d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1943d62866d3SStefano Zampini 
1944d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
1945d5574798SStefano Zampini     }
1946304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1947304d26faSStefano Zampini     if (!n_D) {
1948304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1949304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1950304d26faSStefano Zampini     }
1951304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1952304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1953304d26faSStefano Zampini     /* set ksp_D into pcis data */
1954304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1955304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1956304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1957684f6988SStefano Zampini   }
1958304d26faSStefano Zampini 
1959304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1960684f6988SStefano Zampini   A_RR = 0;
1961684f6988SStefano Zampini   if (neumann) {
1962d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
196304708bb6SStefano Zampini     PetscInt        ibs,mbs;
196404708bb6SStefano Zampini     PetscBool       issbaij;
196504708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
1966f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
19678ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1968f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1969f4ddd8eeSStefano Zampini       PetscInt nn_R;
197081d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1971f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1972f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1973f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1974f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1975f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1976f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1977f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1978727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1979f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1980f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1981f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1982f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1983f4ddd8eeSStefano Zampini         }
1984f4ddd8eeSStefano Zampini       }
1985f4ddd8eeSStefano Zampini       /* last check */
1986d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1987f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1988f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1989f4ddd8eeSStefano Zampini       }
1990f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1991f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1992f4ddd8eeSStefano Zampini     }
1993f4ddd8eeSStefano Zampini     /* extract A_RR */
1994af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1995af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
199604708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
199704708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
199804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
199904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
200004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2001af732b37SStefano Zampini       } else {
200204708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
20036816873aSStefano Zampini       }
200404708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
200504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
200604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
200704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
200804708bb6SStefano Zampini       } else {
200904708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
201004708bb6SStefano Zampini       }
201104708bb6SStefano Zampini     }
201204708bb6SStefano Zampini     if (!sub_schurs->reuse_mumps) {
2013f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
20143301b35fSStefano Zampini       if (pcbddc->local_mat->symmetric_set) {
20153301b35fSStefano Zampini         ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
20166816873aSStefano Zampini       }
20176816873aSStefano Zampini     } else {
20186816873aSStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
20196816873aSStefano Zampini 
20206816873aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
20216816873aSStefano Zampini       ierr = PCGetOperators(reuse_mumps->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
20226816873aSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2023af732b37SStefano Zampini     }
2024f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
2025304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
2026304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
2027304d26faSStefano Zampini       /* default */
2028304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
2029e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
2030304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
20319577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
20329577ea80SStefano Zampini       if (issbaij) {
20339577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
20349577ea80SStefano Zampini       } else {
2035304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
20369577ea80SStefano Zampini       }
2037304d26faSStefano Zampini       /* Allow user's customization */
2038304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
2039304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2040304d26faSStefano Zampini     }
2041d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2042304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2043304d26faSStefano Zampini     if (!n_R) {
2044304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2045304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2046304d26faSStefano Zampini     }
2047d62866d3SStefano Zampini     /* Reuse MUMPS solver if it is present */
2048d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2049d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2050d62866d3SStefano Zampini 
2051d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
2052d62866d3SStefano Zampini     }
2053304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
2054304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2055684f6988SStefano Zampini   }
20566816873aSStefano Zampini   /* free Neumann problem's matrix */
20576816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2058304d26faSStefano Zampini 
2059304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
20600fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2061684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
2062684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2063684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2064684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2065684f6988SStefano Zampini     }
2066684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
20670fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
20680fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
20690fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
20700fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
20710fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2072304d26faSStefano Zampini       /* need to be adapted? */
2073b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2074b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2075b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2076304d26faSStefano Zampini       /* print info */
2077304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2078e604994aSStefano 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);
2079304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2080304d26faSStefano Zampini       }
2081b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2082298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2083304d26faSStefano Zampini       }
2084684f6988SStefano Zampini     }
2085684f6988SStefano Zampini     if (neumann) { /* Neumann */
20866816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
20870fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
20880fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
20890fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
20900fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
20910fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2092304d26faSStefano Zampini       /* need to be adapted? */
2093b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2094b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2095304d26faSStefano Zampini       /* print info */
2096304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2097e604994aSStefano 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);
2098304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2099304d26faSStefano Zampini       }
2100b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2101298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2102304d26faSStefano Zampini       }
21030fccc4e9SStefano Zampini     }
2104684f6988SStefano Zampini   }
2105304d26faSStefano Zampini   PetscFunctionReturn(0);
2106304d26faSStefano Zampini }
2107304d26faSStefano Zampini 
2108304d26faSStefano Zampini #undef __FUNCT__
2109ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
211080677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2111674ae819SStefano Zampini {
2112674ae819SStefano Zampini   PetscErrorCode  ierr;
2113674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2114be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2115674ae819SStefano Zampini 
2116674ae819SStefano Zampini   PetscFunctionBegin;
2117be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
211880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
211920c7b377SStefano Zampini   }
212080677318SStefano Zampini   if (!pcbddc->switch_static) {
212180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
212280677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
212380677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
212420c7b377SStefano Zampini     }
2125be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
212680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212820c7b377SStefano Zampini     } else {
2129be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2130be83ff47SStefano Zampini 
213153892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213253892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213320c7b377SStefano Zampini     }
2134be83ff47SStefano Zampini   } else {
213580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
214080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
214180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
214280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2144674ae819SStefano Zampini     }
2145674ae819SStefano Zampini   }
2146be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
214780677318SStefano Zampini     if (applytranspose) {
214880677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
214980677318SStefano Zampini     } else {
215080677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
215180677318SStefano Zampini     }
215253892102SStefano Zampini #if defined(PETSC_HAVE_MUMPS)
2153be83ff47SStefano Zampini   } else {
2154be83ff47SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2155be83ff47SStefano Zampini 
2156be83ff47SStefano Zampini     if (applytranspose) {
215753892102SStefano Zampini       ierr = MatMumpsSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2158be83ff47SStefano Zampini     } else {
215953892102SStefano Zampini       ierr = MatMumpsSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2160be83ff47SStefano Zampini     }
216153892102SStefano Zampini #endif
2162be83ff47SStefano Zampini   }
216380677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
216480677318SStefano Zampini   if (!pcbddc->switch_static) {
2165be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
216680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
216780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2168be83ff47SStefano Zampini     } else {
2169be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2170be83ff47SStefano Zampini 
217153892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
217253892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2173be83ff47SStefano Zampini     }
217480677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
217580677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
217680677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
217780677318SStefano Zampini     }
217880677318SStefano Zampini   } else {
217980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218380677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
218480677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
218580677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
218680677318SStefano Zampini     }
218780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
219080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2191674ae819SStefano Zampini   }
2192674ae819SStefano Zampini   PetscFunctionReturn(0);
2193674ae819SStefano Zampini }
2194674ae819SStefano Zampini 
2195dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2196674ae819SStefano Zampini #undef __FUNCT__
2197674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2198dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2199674ae819SStefano Zampini {
2200674ae819SStefano Zampini   PetscErrorCode ierr;
2201674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2202674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2203674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2204674ae819SStefano Zampini 
2205674ae819SStefano Zampini   PetscFunctionBegin;
2206dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2207dc359a40SStefano Zampini   if (applytranspose) {
2208674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
22098eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2210dc359a40SStefano Zampini   } else {
2211674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2212674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
221315aaf578SStefano Zampini   }
2214efc2fbd9SStefano Zampini 
2215efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
2216c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
2217efc2fbd9SStefano Zampini     PetscScalar *array;
2218efc2fbd9SStefano Zampini 
2219efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2220efc2fbd9SStefano Zampini     array[pcbddc->local_primal_size-1] += pcbddc->benign_p0;
2221efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2222efc2fbd9SStefano Zampini   }
2223efc2fbd9SStefano Zampini 
222412edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
222512edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
222612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
222712edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
222812edc857SStefano Zampini 
22299f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
223012edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
223112edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
223251694757SStefano Zampini     Mat coarse_mat;
2233964fefecSStefano Zampini     Vec rhs,sol;
223451694757SStefano Zampini     MatNullSpace nullsp;
2235964fefecSStefano Zampini 
2236964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2237964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
223851694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
223951694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
224051694757SStefano Zampini     if (nullsp) {
224151694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
224251694757SStefano Zampini     }
224312edc857SStefano Zampini     if (applytranspose) {
2244964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
224512edc857SStefano Zampini     } else {
2246964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
224712edc857SStefano Zampini     }
224851694757SStefano Zampini     if (nullsp) {
224951694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
225051694757SStefano Zampini     }
225112edc857SStefano Zampini   }
2252674ae819SStefano Zampini 
2253674ae819SStefano Zampini   /* Local solution on R nodes */
225480677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
225580677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
22569f00e9b4SStefano Zampini   }
2257674ae819SStefano Zampini 
22589f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
22599f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
226012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2261674ae819SStefano Zampini 
2262674ae819SStefano Zampini   /* Sum contributions from two levels */
2263dc359a40SStefano Zampini   if (applytranspose) {
2264dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2265dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2266dc359a40SStefano Zampini   } else {
2267674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
22688eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2269dc359a40SStefano Zampini   }
2270efc2fbd9SStefano Zampini   /* store p0 */
2271c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
2272efc2fbd9SStefano Zampini     PetscScalar *array;
2273efc2fbd9SStefano Zampini 
2274efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2275efc2fbd9SStefano Zampini     pcbddc->benign_p0 = array[pcbddc->local_primal_size-1];
2276efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2277efc2fbd9SStefano Zampini   }
2278674ae819SStefano Zampini   PetscFunctionReturn(0);
2279674ae819SStefano Zampini }
2280674ae819SStefano Zampini 
2281674ae819SStefano Zampini #undef __FUNCT__
2282674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
228312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2284674ae819SStefano Zampini {
2285674ae819SStefano Zampini   PetscErrorCode ierr;
2286674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
228758da7f69SStefano Zampini   PetscScalar    *array;
228812edc857SStefano Zampini   Vec            from,to;
2289674ae819SStefano Zampini 
2290674ae819SStefano Zampini   PetscFunctionBegin;
229112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
229212edc857SStefano Zampini     from = pcbddc->coarse_vec;
229312edc857SStefano Zampini     to = pcbddc->vec1_P;
229412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
229512edc857SStefano Zampini       Vec tvec;
229658da7f69SStefano Zampini 
229758da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
229858da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
229912edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
230058da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
230158da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
230258da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
230312edc857SStefano Zampini     }
230412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
230512edc857SStefano Zampini     from = pcbddc->vec1_P;
230612edc857SStefano Zampini     to = pcbddc->coarse_vec;
230712edc857SStefano Zampini   }
230812edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2309674ae819SStefano Zampini   PetscFunctionReturn(0);
2310674ae819SStefano Zampini }
2311674ae819SStefano Zampini 
2312674ae819SStefano Zampini #undef __FUNCT__
2313674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
231412edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
2315674ae819SStefano Zampini {
2316674ae819SStefano Zampini   PetscErrorCode ierr;
2317674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
231858da7f69SStefano Zampini   PetscScalar    *array;
231912edc857SStefano Zampini   Vec            from,to;
2320674ae819SStefano Zampini 
2321674ae819SStefano Zampini   PetscFunctionBegin;
232212edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
232312edc857SStefano Zampini     from = pcbddc->coarse_vec;
232412edc857SStefano Zampini     to = pcbddc->vec1_P;
232512edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
232612edc857SStefano Zampini     from = pcbddc->vec1_P;
232712edc857SStefano Zampini     to = pcbddc->coarse_vec;
232812edc857SStefano Zampini   }
232912edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
233012edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
233112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
233212edc857SStefano Zampini       Vec tvec;
233358da7f69SStefano Zampini 
233412edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
233558da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
233658da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
233758da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
233858da7f69SStefano Zampini     }
233958da7f69SStefano Zampini   } else {
234058da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
234158da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
234212edc857SStefano Zampini     }
234312edc857SStefano Zampini   }
2344674ae819SStefano Zampini   PetscFunctionReturn(0);
2345674ae819SStefano Zampini }
2346674ae819SStefano Zampini 
2347984c4197SStefano Zampini /* uncomment for testing purposes */
2348984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
2349674ae819SStefano Zampini #undef __FUNCT__
2350674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
2351674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
2352674ae819SStefano Zampini {
2353674ae819SStefano Zampini   PetscErrorCode    ierr;
2354674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
2355674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
2356674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
2357984c4197SStefano Zampini   /* one and zero */
2358984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
2359984c4197SStefano Zampini   /* space to store constraints and their local indices */
23609162d606SStefano Zampini   PetscScalar       *constraints_data;
23619162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
23629162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
23639162d606SStefano Zampini   PetscInt          *constraints_n;
2364984c4197SStefano Zampini   /* iterators */
2365b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
2366984c4197SStefano Zampini   /* BLAS integers */
2367e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
2368e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2369c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2370727cdba6SStefano Zampini   /* reuse */
23710e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
23720e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2373984c4197SStefano Zampini   /* change of basis */
2374b3d85658SStefano Zampini   PetscBool         qr_needed;
23759162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
2376984c4197SStefano Zampini   /* auxiliary stuff */
237764efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
23788a0068c3SStefano Zampini   PetscInt          ncc;
2379984c4197SStefano Zampini   /* some quantities */
238045a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2381a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2382984c4197SStefano Zampini 
2383674ae819SStefano Zampini   PetscFunctionBegin;
23848e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
23858e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
23868e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2387088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
2388088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
23890e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
23900e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
23910e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
23920e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
23930e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2394088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2395cf5a6209SStefano Zampini 
2396cf5a6209SStefano Zampini   /* print some info */
2397cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
2398cf5a6209SStefano Zampini     IS       vertices;
2399cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
2400cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2401cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2402cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2403cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2404cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2405cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2406fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2407fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2408cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2409cf5a6209SStefano Zampini   }
2410cf5a6209SStefano Zampini 
2411cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
24129162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
2413cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
2414cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
2415cf5a6209SStefano Zampini     Vec          *localnearnullsp;
2416cf5a6209SStefano Zampini     PetscScalar  *array;
2417cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2418cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
2419674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
2420b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
2421674ae819SStefano Zampini     PetscScalar  *work;
2422674ae819SStefano Zampini     PetscReal    *singular_vals;
2423674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2424674ae819SStefano Zampini     PetscReal    *rwork;
2425674ae819SStefano Zampini #endif
2426674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2427674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
2428674ae819SStefano Zampini #else
2429964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
2430964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
2431674ae819SStefano Zampini #endif
2432674ae819SStefano Zampini 
2433674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
2434d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2435d06fc5fdSStefano Zampini     /* free unneeded index sets */
2436d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
2437d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2438674ae819SStefano Zampini     }
2439d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
2440d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
2441d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2442d06fc5fdSStefano Zampini       }
2443d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2444d06fc5fdSStefano Zampini       n_ISForEdges = 0;
2445d06fc5fdSStefano Zampini     }
2446d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
2447d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
2448d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2449d06fc5fdSStefano Zampini       }
2450d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2451d06fc5fdSStefano Zampini       n_ISForFaces = 0;
2452d06fc5fdSStefano Zampini     }
245370022509SStefano Zampini 
245470022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
245570022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
245670022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
245770022509SStefano Zampini     if (pcbddc->NullSpace) {
245870022509SStefano Zampini       PetscBool tbool[2],gbool[2];
245970022509SStefano Zampini 
246070022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2461b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
2462d06fc5fdSStefano Zampini         if (!ISForEdges) {
2463d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
2464d06fc5fdSStefano Zampini         }
2465b8ffe317SStefano Zampini       }
2466d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
2467d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
2468d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2469d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
2470d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
247198a51de6SStefano Zampini     }
247270022509SStefano Zampini #endif
247308122e43SStefano Zampini 
2474674ae819SStefano Zampini     /* check if near null space is attached to global mat */
2475674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2476674ae819SStefano Zampini     if (nearnullsp) {
2477674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2478f4ddd8eeSStefano Zampini       /* remove any stored info */
2479f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2480f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2481f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
2482f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2483f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
2484473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2485f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
2486f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2487f4ddd8eeSStefano Zampini       }
2488984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
2489984c4197SStefano Zampini       nnsp_size = 0;
2490674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
2491674ae819SStefano Zampini     }
2492984c4197SStefano Zampini     /* get max number of constraints on a single cc */
2493984c4197SStefano Zampini     max_constraints = nnsp_size;
2494984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
2495984c4197SStefano Zampini 
2496674ae819SStefano Zampini     /*
2497674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
24989162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
24999162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
25009162d606SStefano Zampini          There can be multiple constraints per connected component
2501674ae819SStefano Zampini                                                                                                                                                            */
2502674ae819SStefano Zampini     n_vertices = 0;
2503674ae819SStefano Zampini     if (ISForVertices) {
2504674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2505674ae819SStefano Zampini     }
25069162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
25079162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
25089162d606SStefano Zampini 
25099162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
25109162d606SStefano Zampini     total_counts *= max_constraints;
2511674ae819SStefano Zampini     total_counts += n_vertices;
25124641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
25139162d606SStefano Zampini 
2514674ae819SStefano Zampini     total_counts = 0;
2515674ae819SStefano Zampini     max_size_of_constraint = 0;
2516674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
25179162d606SStefano Zampini       IS used_is;
2518674ae819SStefano Zampini       if (i<n_ISForEdges) {
25199162d606SStefano Zampini         used_is = ISForEdges[i];
2520674ae819SStefano Zampini       } else {
25219162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
2522674ae819SStefano Zampini       }
25239162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2524674ae819SStefano Zampini       total_counts += j;
2525674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2526674ae819SStefano Zampini     }
25279162d606SStefano 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);
25289162d606SStefano Zampini 
2529984c4197SStefano Zampini     /* get local part of global near null space vectors */
2530785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2531984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2532984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2533e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2534e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2535984c4197SStefano Zampini     }
2536674ae819SStefano Zampini 
2537242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
2538242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
2539a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2540242a89d7SStefano Zampini 
2541984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2542a773dcb8SStefano Zampini     if (!skip_lapack) {
2543674ae819SStefano Zampini       PetscScalar temp_work;
2544911cabfeSStefano Zampini 
2545674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2546984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2547785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2548785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2549785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2550674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2551785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2552674ae819SStefano Zampini #endif
2553674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2554c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2555c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2556674ae819SStefano Zampini       lwork = -1;
2557674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2558674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2559c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2560674ae819SStefano Zampini #else
2561c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2562674ae819SStefano Zampini #endif
2563674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2564984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2565674ae819SStefano Zampini #else /* on missing GESVD */
2566674ae819SStefano Zampini       /* SVD */
2567674ae819SStefano Zampini       PetscInt max_n,min_n;
2568674ae819SStefano Zampini       max_n = max_size_of_constraint;
2569984c4197SStefano Zampini       min_n = max_constraints;
2570984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
2571674ae819SStefano Zampini         min_n = max_size_of_constraint;
2572984c4197SStefano Zampini         max_n = max_constraints;
2573674ae819SStefano Zampini       }
2574785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2575674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2576785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2577674ae819SStefano Zampini #endif
2578674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2579674ae819SStefano Zampini       lwork = -1;
2580e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2581e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2582b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2583674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2584674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
25859162d606SStefano 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));
2586674ae819SStefano Zampini #else
25879162d606SStefano 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));
2588674ae819SStefano Zampini #endif
2589674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2590984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2591984c4197SStefano Zampini #endif /* on missing GESVD */
2592674ae819SStefano Zampini       /* Allocate optimal workspace */
2593674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2594854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2595674ae819SStefano Zampini     }
2596674ae819SStefano Zampini     /* Now we can loop on constraining sets */
2597674ae819SStefano Zampini     total_counts = 0;
25989162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
25999162d606SStefano Zampini     constraints_data_ptr[0] = 0;
2600674ae819SStefano Zampini     /* vertices */
26019162d606SStefano Zampini     if (n_vertices) {
2602674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
26039162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2604674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
26059162d606SStefano Zampini         constraints_n[total_counts] = 1;
26069162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
26079162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
26089162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2609674ae819SStefano Zampini         total_counts++;
2610674ae819SStefano Zampini       }
2611674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2612674ae819SStefano Zampini       n_vertices = total_counts;
2613674ae819SStefano Zampini     }
2614984c4197SStefano Zampini 
2615674ae819SStefano Zampini     /* edges and faces */
26169162d606SStefano Zampini     total_counts_cc = total_counts;
2617911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
26189162d606SStefano Zampini       IS        used_is;
26199162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
26209162d606SStefano Zampini 
2621911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
26229162d606SStefano Zampini         used_is = ISForEdges[ncc];
2623984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2624674ae819SStefano Zampini       } else {
26259162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
2626984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2627674ae819SStefano Zampini       }
2628674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
26299162d606SStefano Zampini 
26309162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
26319162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2632984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
2633984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2634674ae819SStefano Zampini       if (nnsp_has_cnst) {
26355b08dc53SStefano Zampini         PetscScalar quad_value;
26369162d606SStefano Zampini 
26379162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
26389162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
26399162d606SStefano Zampini 
2640a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
2641674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2642a773dcb8SStefano Zampini         } else {
2643a773dcb8SStefano Zampini           quad_value = 1.0;
2644a773dcb8SStefano Zampini         }
2645674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
26469162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
2647674ae819SStefano Zampini         }
26489162d606SStefano Zampini         temp_constraints++;
2649674ae819SStefano Zampini         total_counts++;
2650674ae819SStefano Zampini       }
2651674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
2652984c4197SStefano Zampini         PetscReal real_value;
26539162d606SStefano Zampini         PetscScalar *ptr_to_data;
26549162d606SStefano Zampini 
2655984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
26569162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
2657674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
26589162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
2659674ae819SStefano Zampini         }
2660984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2661984c4197SStefano Zampini         /* check if array is null on the connected component */
2662e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
26639162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
26645b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2665674ae819SStefano Zampini           temp_constraints++;
2666674ae819SStefano Zampini           total_counts++;
26679162d606SStefano Zampini           if (!idxs_copied) {
26689162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
26699162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
2670674ae819SStefano Zampini           }
2671674ae819SStefano Zampini         }
26729162d606SStefano Zampini       }
26739162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
267445a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2675eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2676a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
26779162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
26789162d606SStefano Zampini 
26799162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2680a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
26819162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
2682a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
26839162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
2684a773dcb8SStefano Zampini         } else { /* perform SVD */
2685984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
26869162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2687674ae819SStefano Zampini 
2688674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2689984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
2690984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
2691984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
2692984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
2693984c4197SStefano Zampini                 from that computed using LAPACKgesvd
2694984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
2695984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
2696984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
2697674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
2698e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2699984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2700674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
2701674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
27029162d606SStefano 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));
2703674ae819SStefano Zampini             }
2704674ae819SStefano Zampini           }
2705e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
2706e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2707e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
2708674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2709c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
2710674ae819SStefano Zampini #else
2711c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
2712674ae819SStefano Zampini #endif
2713674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2714984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
2715984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
2716674ae819SStefano Zampini           j = 0;
2717984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
2718674ae819SStefano Zampini           total_counts = total_counts-j;
271945a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
2720e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
2721c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2722c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2723c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
2724c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2725c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
2726c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2727674ae819SStefano Zampini           if (j<temp_constraints) {
2728984c4197SStefano Zampini             PetscInt ii;
2729984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
2730674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27319162d606SStefano 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));
2732674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2733984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
2734674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
27359162d606SStefano 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];
2736674ae819SStefano Zampini               }
2737674ae819SStefano Zampini             }
2738674ae819SStefano Zampini           }
2739674ae819SStefano Zampini #else  /* on missing GESVD */
2740e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2741e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2742b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2743674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2744674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
27459162d606SStefano 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));
2746674ae819SStefano Zampini #else
27479162d606SStefano 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));
2748674ae819SStefano Zampini #endif
2749984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
2750674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2751984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
2752e310c8b4SStefano Zampini           k = temp_constraints;
2753e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
2754674ae819SStefano Zampini           j = 0;
2755e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
275645a1bb75SStefano Zampini           valid_constraints = k-j;
2757911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
2758984c4197SStefano Zampini #endif /* on missing GESVD */
2759674ae819SStefano Zampini         }
2760a773dcb8SStefano Zampini       }
27619162d606SStefano Zampini       /* update pointers information */
27629162d606SStefano Zampini       if (valid_constraints) {
27639162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
27649162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
27659162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
27669162d606SStefano Zampini         /* set change_of_basis flag */
276745a1bb75SStefano Zampini         if (boolforchange) {
2768b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
27699162d606SStefano Zampini         }
2770b3d85658SStefano Zampini         total_counts_cc++;
277145a1bb75SStefano Zampini       }
277245a1bb75SStefano Zampini     }
2773984c4197SStefano Zampini     /* free workspace */
27748f1c130eSStefano Zampini     if (!skip_lapack) {
2775984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
2776984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2777984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
2778984c4197SStefano Zampini #endif
2779984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
2780984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2781984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
2782984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2783984c4197SStefano Zampini #endif
2784984c4197SStefano Zampini     }
2785984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2786984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
2787984c4197SStefano Zampini     }
2788984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
2789cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
2790cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
2791cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2792cf5a6209SStefano Zampini     }
2793cf5a6209SStefano Zampini     if (n_ISForFaces) {
2794cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2795cf5a6209SStefano Zampini     }
2796cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
2797cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2798cf5a6209SStefano Zampini     }
2799cf5a6209SStefano Zampini     if (n_ISForEdges) {
2800cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2801cf5a6209SStefano Zampini     }
2802cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
280308122e43SStefano Zampini   } else {
280408122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2805984c4197SStefano Zampini 
280608122e43SStefano Zampini     total_counts = 0;
280708122e43SStefano Zampini     n_vertices = 0;
2808d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
2809d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
281008122e43SStefano Zampini     }
281108122e43SStefano Zampini     max_constraints = 0;
28129162d606SStefano Zampini     total_counts_cc = 0;
281308122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
281408122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
28159162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
281608122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
281708122e43SStefano Zampini     }
28189162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
28199162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
28209162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
28219162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
282274d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
28239162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
28249162d606SStefano Zampini     total_counts_cc = 0;
28259162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
28269162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
28279162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
282808122e43SStefano Zampini       }
282908122e43SStefano Zampini     }
28309162d606SStefano Zampini #if 0
28319162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
28329162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
28339162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
28349162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
28359162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
28369162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
28379162d606SStefano Zampini       }
28389162d606SStefano Zampini       printf("\n");
28399162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
28409162d606SStefano Zampini     }
28411b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
28428bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
28431b968477SStefano Zampini     }
28441b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
28458bec7fa6SStefano 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]);
28461b968477SStefano Zampini     }
284708122e43SStefano Zampini #endif
284808122e43SStefano Zampini 
28498bec7fa6SStefano Zampini     max_size_of_constraint = 0;
28509162d606SStefano 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]);
28519162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
285208122e43SStefano Zampini     /* Change of basis */
2853b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
285408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
285508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
285608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
2857b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
285808122e43SStefano Zampini         }
285908122e43SStefano Zampini       }
286008122e43SStefano Zampini     }
286108122e43SStefano Zampini   }
2862984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
2863019a44ceSStefano Zampini   /* allocating one extra space (in case an extra primal dof should be stored for the benign trick */
2864019a44ceSStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+1,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
286508122e43SStefano Zampini 
28669162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
28679162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
28689162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
28699162d606SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",constraints_idxs_ptr[total_counts_cc],i);
287008122e43SStefano Zampini   }
2871674ae819SStefano Zampini 
2872674ae819SStefano Zampini   /* Create constraint matrix */
2873674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
287416f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
2875984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
2876984c4197SStefano Zampini 
2877984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
2878a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
2879a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
288074d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
2881984c4197SStefano Zampini   total_primal_vertices=0;
2882b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
28839162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
28849162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2885984c4197SStefano Zampini     if (size_of_constraint == 1) {
28869162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
2887b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
288864efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
28899162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
28909162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
2891a717540cSStefano Zampini       }
2892b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
289374d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
2894a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
2895a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
2896a717540cSStefano Zampini       }
2897fa434743SStefano Zampini     } else {
2898b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
2899fa434743SStefano Zampini     }
2900a717540cSStefano Zampini   }
2901b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
2902b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
2903674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
290470022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2905b3d85658SStefano Zampini 
2906019a44ceSStefano Zampini   /* allocating one extra space (in case an extra primal dof should be stored for the benign trick */
2907019a44ceSStefano Zampini   ierr = PetscMalloc2(pcbddc->local_primal_size_cc+1,&pcbddc->local_primal_ref_node,pcbddc->local_primal_size_cc+1,&pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
29080e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
29090e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
2910984c4197SStefano Zampini 
2911984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
291274d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
2913785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2914984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
291574d5cdf7SStefano Zampini 
2916984c4197SStefano Zampini   j = total_primal_vertices;
291774d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
2918b3d85658SStefano Zampini   cum = total_primal_vertices;
29199162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
29204641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2921b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
2922b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
2923b3d85658SStefano Zampini       cum++;
29249162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
292574d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
292674d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
292774d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
292874d5cdf7SStefano Zampini       }
29299162d606SStefano Zampini       j += constraints_n[i];
2930674ae819SStefano Zampini     }
2931674ae819SStefano Zampini   }
2932674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2933674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2934088faed8SStefano Zampini 
2935674ae819SStefano Zampini   /* set values in constraint matrix */
2936984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
29370e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2938674ae819SStefano Zampini   }
2939984c4197SStefano Zampini   total_counts = total_primal_vertices;
29409162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
29414641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
29429162d606SStefano Zampini       PetscInt *cols;
29439162d606SStefano Zampini 
29449162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
29459162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
29469162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
29479162d606SStefano Zampini         PetscInt    row = total_counts+k;
29489162d606SStefano Zampini         PetscScalar *vals;
29499162d606SStefano Zampini 
29509162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
29519162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
29529162d606SStefano Zampini       }
29539162d606SStefano Zampini       total_counts += constraints_n[i];
2954674ae819SStefano Zampini     }
2955674ae819SStefano Zampini   }
2956674ae819SStefano Zampini   /* assembling */
2957674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2958674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2959088faed8SStefano Zampini 
2960984c4197SStefano Zampini   /*
296145a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2962984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2963984c4197SStefano Zampini   */
2964674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2965674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2966026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2967984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2968984c4197SStefano Zampini     /* working stuff for GEQRF */
296981d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2970984c4197SStefano Zampini     PetscBLASInt lqr_work;
2971984c4197SStefano Zampini     /* working stuff for UNGQR */
2972984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2973984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2974984c4197SStefano Zampini     /* working stuff for TRTRS */
2975984c4197SStefano Zampini     PetscScalar  *trs_rhs;
29763f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2977984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2978984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2979984c4197SStefano Zampini     PetscScalar  *start_vals;
2980984c4197SStefano Zampini     /* working stuff for values insertion */
29814641a718SStefano Zampini     PetscBT      is_primal;
298264efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
2983906d46d4SStefano Zampini     /* matrix sizes */
2984906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2985906d46d4SStefano Zampini     /* temporary change of basis */
2986906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2987cf5a6209SStefano Zampini     /* extra space for debugging */
2988cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
2989984c4197SStefano Zampini 
2990906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2991906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
299216f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2993bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
2994906d46d4SStefano Zampini     /* nonzeros for local mat */
2995bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
2996bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
29979162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
2998a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
29999162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3000a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
30019162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
3002a717540cSStefano Zampini         } else {
30039162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
30049162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
3005a717540cSStefano Zampini         }
3006a717540cSStefano Zampini       }
3007a717540cSStefano Zampini     }
3008906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
3009bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3010a717540cSStefano Zampini     /* Set initial identity in the matrix */
3011bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
3012906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3013a717540cSStefano Zampini     }
3014a717540cSStefano Zampini 
3015a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
3016a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3017a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3018a717540cSStefano Zampini     }
3019a717540cSStefano Zampini 
3020a717540cSStefano Zampini 
3021a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
3022a717540cSStefano Zampini     /*
3023a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3024a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3025a717540cSStefano Zampini 
3026a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
3027a717540cSStefano Zampini 
3028a6b551f4SStefano 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)
3029a6b551f4SStefano Zampini 
3030a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
3031a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
3032a717540cSStefano Zampini             |              ...                        |
3033a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
3034a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3035a717540cSStefano Zampini 
3036a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
3037a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3038a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3039a6b551f4SStefano Zampini 
3040a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
3041a717540cSStefano Zampini     */
3042a717540cSStefano Zampini     if (qr_needed) {
3043984c4197SStefano Zampini       /* space to store Q */
3044854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3045984c4197SStefano Zampini       /* first we issue queries for optimal work */
30463f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
30473f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
30483f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3049984c4197SStefano Zampini       lqr_work = -1;
30503f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3051984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3052984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3053785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3054984c4197SStefano Zampini       lgqr_work = -1;
30553f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
30563f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
30573f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
30583f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
30593f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
30603f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3061984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3062984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3063785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3064984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3065785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3066984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3067785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3068a717540cSStefano Zampini       /* allocating workspace for check */
3069a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3070cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3071a717540cSStefano Zampini       }
3072a717540cSStefano Zampini     }
3073984c4197SStefano Zampini     /* array to store whether a node is primal or not */
30744641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3075473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
30760e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
307739e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
307839e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
30794641a718SStefano Zampini     }
308039e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
308139e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
308239e2fb2aSStefano Zampini     }
308339e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3084984c4197SStefano Zampini 
3085a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
30869162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
30879162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
30884641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3089984c4197SStefano Zampini         /* get constraint info */
30909162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3091984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3092984c4197SStefano Zampini 
3093984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
30949162d606SStefano 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);
3095674ae819SStefano Zampini         }
3096984c4197SStefano Zampini 
3097fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3098a717540cSStefano Zampini 
3099a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3100a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
31019162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3102a717540cSStefano Zampini           }
3103984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
31049162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3105984c4197SStefano Zampini 
3106984c4197SStefano Zampini           /* compute QR decomposition of constraints */
31073f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
31083f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
31093f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3110674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31113f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3112984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3113674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3114984c4197SStefano Zampini 
3115984c4197SStefano Zampini           /* explictly compute R^-T */
3116984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3117984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
31183f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
31193f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
31203f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
31213f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3122984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31233f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3124984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3125984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3126984c4197SStefano Zampini 
3127a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
31283f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
31293f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
31303f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
31313f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3132984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31333f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3134984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3135984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3136984c4197SStefano Zampini 
3137984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3138984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3139984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
31403f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
31413f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
31423f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
31433f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
31443f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
31453f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3146984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31479162d606SStefano 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));
3148984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
31499162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3150984c4197SStefano Zampini 
3151984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
31529162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3153984c4197SStefano Zampini           /* insert cols for primal dofs */
3154984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3155984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
31569162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3157906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3158984c4197SStefano Zampini           }
3159984c4197SStefano Zampini           /* insert cols for dual dofs */
3160984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
31619162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3162984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
31639162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3164906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3165984c4197SStefano Zampini               j++;
3166674ae819SStefano Zampini             }
3167674ae819SStefano Zampini           }
3168984c4197SStefano Zampini 
3169984c4197SStefano Zampini           /* check change of basis */
3170984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3171984c4197SStefano Zampini             PetscInt   ii,jj;
3172984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3173c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3174c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3175c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3176c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3177c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3178c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3179984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3180cf5a6209SStefano 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));
3181984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3182984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3183984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3184cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3185cf5a6209SStefano 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;
3186674ae819SStefano Zampini               }
3187674ae819SStefano Zampini             }
3188984c4197SStefano Zampini             if (!valid_qr) {
318922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3190984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3191984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3192cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3193cf5a6209SStefano 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]));
3194674ae819SStefano Zampini                   }
3195cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3196cf5a6209SStefano 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]));
3197984c4197SStefano Zampini                   }
3198984c4197SStefano Zampini                 }
3199984c4197SStefano Zampini               }
3200674ae819SStefano Zampini             } else {
320122d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3202674ae819SStefano Zampini             }
3203674ae819SStefano Zampini           }
3204a717540cSStefano Zampini         } else { /* simple transformation block */
3205a717540cSStefano Zampini           PetscInt    row,col;
3206a6b551f4SStefano Zampini           PetscScalar val,norm;
3207a6b551f4SStefano Zampini 
3208a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
32099162d606SStefano 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));
3210a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
32119162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
32129162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3213bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
32149162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3215906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
32169162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3217a717540cSStefano Zampini             } else {
3218a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
32199162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3220a717540cSStefano Zampini                 if (row != col) {
32219162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3222a717540cSStefano Zampini                 } else {
32239162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3224a717540cSStefano Zampini                 }
3225906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3226a717540cSStefano Zampini               }
3227a717540cSStefano Zampini             }
3228a717540cSStefano Zampini           }
322998a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
323022d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3231a717540cSStefano Zampini           }
3232674ae819SStefano Zampini         }
3233984c4197SStefano Zampini       } else {
3234984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
32359162d606SStefano 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);
3236674ae819SStefano Zampini         }
3237674ae819SStefano Zampini       }
3238674ae819SStefano Zampini     }
3239a717540cSStefano Zampini 
3240a717540cSStefano Zampini     /* free workspace */
3241a717540cSStefano Zampini     if (qr_needed) {
3242984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
3243cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3244984c4197SStefano Zampini       }
3245984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3246984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3247984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3248984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3249984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3250674ae819SStefano Zampini     }
3251a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3252906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3253906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3254906d46d4SStefano Zampini 
3255906d46d4SStefano Zampini     /* assembling of global change of variable */
3256bbb9e6c6SStefano Zampini     {
3257bbb9e6c6SStefano Zampini       Mat      tmat;
325816f15bc4SStefano Zampini       PetscInt bs;
325916f15bc4SStefano Zampini 
3260906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3261906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3262bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3263bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3264bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3265bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
326616f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
326716f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3268906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3269bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3270bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3271bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3272bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3273bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3274e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3275e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3276bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3277bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3278906d46d4SStefano Zampini     }
3279906d46d4SStefano Zampini     /* check */
3280906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
3281906d46d4SStefano Zampini       PetscReal error;
3282906d46d4SStefano Zampini       Vec       x,x_change;
3283906d46d4SStefano Zampini 
3284906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3285906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3286906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3287906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3288e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3289e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3290bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
3291e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3292e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3293906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
3294906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3295906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3296906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3297bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
3298906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
3299906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3300906d46d4SStefano Zampini     }
3301b96c3477SStefano Zampini 
3302b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
3303b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
3304b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
3305b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
3306ac632422SStefano Zampini         Mat                    S_new,tmat;
3307b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
3308b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
3309b087196eSStefano Zampini         const PetscScalar      *array;
3310b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
3311b087196eSStefano Zampini         PetscInt               i,n_V;
3312bbb9e6c6SStefano Zampini 
3313bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
33146816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
3315b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
3316b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
3317b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
3318b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
3319bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
3320b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
3321ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3322b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
3323ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3324b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3325b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
3326b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3327b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3328b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
3329b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
3330b087196eSStefano Zampini           PetscScalar val;
3331b087196eSStefano Zampini           PetscInt    idx;
3332b087196eSStefano Zampini 
3333b087196eSStefano Zampini           idx = idxs_V[i];
3334b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
3335b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
3336b087196eSStefano Zampini         }
3337b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3338b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3339ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
3340ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3341ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
3342ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3343b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
3344ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3345b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3346ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
3347ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3348ac632422SStefano Zampini         }
3349b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
3350b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3351b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3352b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3353b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
3354b96c3477SStefano Zampini       }
3355b96c3477SStefano Zampini     }
3356906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
3357906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
3358b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3359b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
3360b9b85e73SStefano Zampini   }
3361906d46d4SStefano Zampini 
3362906d46d4SStefano Zampini   /* set up change of basis context */
3363906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
3364906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
3365906d46d4SStefano Zampini 
3366906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
3367906d46d4SStefano Zampini       PetscInt global_size,local_size;
3368906d46d4SStefano Zampini 
3369906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3370906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3371906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
3372906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3373906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
3374906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
3375906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3376906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3377906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3378906d46d4SStefano Zampini     } else {
3379906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3380906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3381906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3382906d46d4SStefano Zampini     }
3383906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
3384906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3385906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3386906d46d4SStefano Zampini     } else {
3387906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3388906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3389906d46d4SStefano Zampini     }
3390906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3391906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3392906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3393906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3394b9b85e73SStefano Zampini   }
3395a717540cSStefano Zampini 
3396019a44ceSStefano Zampini   /* add pressure dof to set of primal nodes for numbering purposes */
3397c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
3398c9ed8603SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx;
3399d16cbb6bSStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx;
3400019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
3401019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
3402019a44ceSStefano Zampini     pcbddc->local_primal_size++;
3403019a44ceSStefano Zampini   }
3404019a44ceSStefano Zampini 
3405019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
3406727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
3407727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
3408aff50787SStefano Zampini     ierr = PetscMemcmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc*sizeof(PetscScalar),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
3409c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
34100e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
3411aff50787SStefano Zampini       ierr = PetscMemcmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscScalar),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
3412727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3413727cdba6SStefano Zampini     }
34140e6343abSStefano Zampini   }
34150e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3416727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3417727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3418727cdba6SStefano Zampini 
3419a717540cSStefano Zampini   /* flush dbg viewer */
3420b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
3421b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3422b8ffe317SStefano Zampini   }
3423a717540cSStefano Zampini 
3424e310c8b4SStefano Zampini   /* free workspace */
3425a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
34264641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
342708122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
34289162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
34299162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
343008122e43SStefano Zampini   } else {
34319162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
34329162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
34339162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
343408122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
343508122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
34369162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
34379162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
343808122e43SStefano Zampini   }
3439674ae819SStefano Zampini   PetscFunctionReturn(0);
3440674ae819SStefano Zampini }
3441674ae819SStefano Zampini 
3442674ae819SStefano Zampini #undef __FUNCT__
3443674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
3444674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3445674ae819SStefano Zampini {
3446674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3447674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
3448674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
34497fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
3450674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
3451674ae819SStefano Zampini 
3452674ae819SStefano Zampini   PetscFunctionBegin;
34538e61c736SStefano Zampini   /* Reset previously computed graph */
34548e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3455674ae819SStefano Zampini   /* Init local Graph struct */
34567fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
34573bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3458674ae819SStefano Zampini 
3459575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
34605099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
34615099eff2SStefano 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);
3462575ad6abSStefano Zampini   }
34639577ea80SStefano Zampini 
3464674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
34654d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
34664d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
34674d379d7bSStefano Zampini     PetscInt  nvtxs;
3468e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
3469674ae819SStefano Zampini 
34704d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
34712fffb893SStefano Zampini 
34722fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
34732fffb893SStefano Zampini       if (flg_row) {
34744d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3475b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
34762fffb893SStefano Zampini       }
34772fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
34789b28b941SStefano Zampini     } else if (pcbddc->current_level && pcis->n_B) { /* just compute subdomain's connected components for coarser levels when the local boundary is not empty */
34794d379d7bSStefano Zampini       IS                     is_dummy;
34804d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
34814d379d7bSStefano Zampini       PetscInt               j,sum;
34824d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
34834d379d7bSStefano Zampini       const PetscInt         *idxs;
34844d379d7bSStefano Zampini       PCBDDCGraph            graph;
34854d379d7bSStefano Zampini       PetscBT                is_on_boundary;
34864d379d7bSStefano Zampini 
34874d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
34884d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
34894d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
34904d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
34917fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
34924d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3493e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3494e496cd5dSStefano Zampini       if (flg_row) {
34954d379d7bSStefano Zampini         graph->xadj = xadj;
34964d379d7bSStefano Zampini         graph->adjncy = adjncy;
3497e496cd5dSStefano Zampini       }
34984d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
34994d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3500e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
35014d379d7bSStefano Zampini 
35024d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
35039b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
35044d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
35054d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
35064d379d7bSStefano Zampini         }
35074d379d7bSStefano Zampini       }
35084d379d7bSStefano Zampini 
3509e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
35104d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
35114d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
35124d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
35134d379d7bSStefano Zampini       }
35144d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
35154d379d7bSStefano Zampini 
3516e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
35174d379d7bSStefano Zampini       sum = 0;
35184d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
35194d379d7bSStefano Zampini         PetscInt sizecc = 0;
35204d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
35214d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
35224d379d7bSStefano Zampini             sizecc++;
35234d379d7bSStefano Zampini           }
35244d379d7bSStefano Zampini         }
35254d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
35264d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
35274d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
35284d379d7bSStefano Zampini           }
35294d379d7bSStefano Zampini         }
35304d379d7bSStefano Zampini         sum += sizecc*sizecc;
35314d379d7bSStefano Zampini       }
35324d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
35334d379d7bSStefano Zampini       sum = 0;
3534e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
35354d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
35364d379d7bSStefano Zampini         cxadj[i] = sum;
35374d379d7bSStefano Zampini         sum += temp;
35384d379d7bSStefano Zampini       }
3539e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
35404d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
35414d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
35424d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
35434d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
35444d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
35454d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
35464d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
35474d379d7bSStefano Zampini                 sizecc++;
35484d379d7bSStefano Zampini               }
35494d379d7bSStefano Zampini             }
35504d379d7bSStefano Zampini           }
35514d379d7bSStefano Zampini         }
35524d379d7bSStefano Zampini       }
35539b28b941SStefano Zampini       if (sum) {
3554e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
35554d379d7bSStefano Zampini       } else {
35564d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
35574d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
35584d379d7bSStefano Zampini       }
35594d379d7bSStefano Zampini       graph->xadj = 0;
35604d379d7bSStefano Zampini       graph->adjncy = 0;
35614d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
35624d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
35634d379d7bSStefano Zampini     }
3564674ae819SStefano Zampini   }
35659b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
35669b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3567674ae819SStefano Zampini   }
3568674ae819SStefano Zampini 
356963602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3570674ae819SStefano Zampini   vertex_size = 1;
357163602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
357263602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
357395ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
357463602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3575e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
357663602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3577674ae819SStefano Zampini       }
357863602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
357963602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
358063602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3581674ae819SStefano Zampini     }
358263602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3583674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
358463602bcaSStefano Zampini   } else {
358563602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
358663602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3587854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
358863602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
358963602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
359063602bcaSStefano Zampini       }
359163602bcaSStefano Zampini     }
3592674ae819SStefano Zampini   }
3593674ae819SStefano Zampini 
3594674ae819SStefano Zampini   /* Setup of Graph */
3595785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3596e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3597785d1243SStefano Zampini   }
3598785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3599e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3600785d1243SStefano Zampini   }
3601302440fdSBarry Smith   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);CHKERRQ(ierr);
3602674ae819SStefano Zampini 
3603674ae819SStefano Zampini   /* Graph's connected components analysis */
3604674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3605674ae819SStefano Zampini 
3606674ae819SStefano Zampini   /* print some info to stdout */
3607674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3608302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3609674ae819SStefano Zampini   }
3610fb180af4SStefano Zampini 
3611fb180af4SStefano Zampini   /* mark topography has done */
3612fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3613674ae819SStefano Zampini   PetscFunctionReturn(0);
3614674ae819SStefano Zampini }
3615674ae819SStefano Zampini 
3616dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3617674ae819SStefano Zampini #undef __FUNCT__
3618674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3619dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3620674ae819SStefano Zampini {
3621dc456d91SStefano Zampini   PetscSF        sf;
3622dc456d91SStefano Zampini   PetscLayout    map;
3623dc456d91SStefano Zampini   const PetscInt *idxs;
3624dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
3625dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
3626dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
3627dc456d91SStefano Zampini   PetscMPIInt    commsize;
3628674ae819SStefano Zampini   PetscBool      first_found;
3629674ae819SStefano Zampini   PetscErrorCode ierr;
3630674ae819SStefano Zampini 
3631674ae819SStefano Zampini   PetscFunctionBegin;
3632dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
3633dc456d91SStefano Zampini   if (subset_mult) {
3634dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
3635dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
3636dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
3637674ae819SStefano Zampini   }
3638dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
3639dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
3640dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
3641dc456d91SStefano Zampini   for (i=0;i<n;i++) {
3642dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
3643dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
3644674ae819SStefano Zampini   }
3645dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
3646dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3647dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
3648dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
3649dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
3650dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
3651dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
3652dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
3653dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
3654dc456d91SStefano Zampini 
3655dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
3656dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
3657dc456d91SStefano Zampini   if (subset_mult) {
3658dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3659dc456d91SStefano Zampini 
3660dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3661dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
3662dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3663674ae819SStefano Zampini   } else {
3664dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
3665674ae819SStefano Zampini   }
3666dc456d91SStefano Zampini   /* local size of new subset */
3667dc456d91SStefano Zampini   n_n = 0;
3668dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
3669dc456d91SStefano Zampini 
3670dc456d91SStefano Zampini   /* global indexes in layout */
3671dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
3672dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
3673dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
3674dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
3675dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
3676dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
3677dc456d91SStefano Zampini 
3678dc456d91SStefano Zampini   /* reduce from leaves to roots */
3679dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
368064a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
368164a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
3682dc456d91SStefano Zampini 
3683dc456d91SStefano Zampini   /* count indexes in local part of layout */
3684674ae819SStefano Zampini   nlocals = 0;
3685674ae819SStefano Zampini   first_index = -1;
3686674ae819SStefano Zampini   first_found = PETSC_FALSE;
3687dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
3688dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
3689674ae819SStefano Zampini       first_found = PETSC_TRUE;
3690674ae819SStefano Zampini       first_index = i;
3691674ae819SStefano Zampini     }
3692dc456d91SStefano Zampini     nlocals += root_data[i];
3693674ae819SStefano Zampini   }
3694dc456d91SStefano Zampini 
3695dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
36965fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
3697dc456d91SStefano Zampini   start = 0;
369864a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
36995fa240b1SStefano Zampini #else
370064a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
37015fa240b1SStefano Zampini   start = start-nlocals;
37025fa240b1SStefano Zampini #endif
37035fa240b1SStefano Zampini 
3704dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
3705dc456d91SStefano Zampini     *N_n = start + nlocals;
3706dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
3707dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3708674ae819SStefano Zampini   }
37095fa240b1SStefano Zampini 
37105fa240b1SStefano Zampini   /* adapt root data with cumulative */
3711674ae819SStefano Zampini   if (first_found) {
3712dc456d91SStefano Zampini     PetscInt old_index;
3713dc456d91SStefano Zampini 
3714dc456d91SStefano Zampini     root_data[first_index] += start;
3715674ae819SStefano Zampini     old_index = first_index;
3716dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
3717dc456d91SStefano Zampini       if (root_data[i]) {
3718dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
3719674ae819SStefano Zampini         old_index = i;
3720674ae819SStefano Zampini       }
3721674ae819SStefano Zampini     }
3722674ae819SStefano Zampini   }
3723dc456d91SStefano Zampini 
3724dc456d91SStefano Zampini   /* from roots to leaves */
3725dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3726dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3727dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
3728dc456d91SStefano Zampini 
3729dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
3730dc456d91SStefano Zampini   if (subset_mult) {
3731dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3732dc456d91SStefano Zampini     PetscInt        cum;
3733dc456d91SStefano Zampini 
3734dc456d91SStefano Zampini     cum = 0;
3735dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3736dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3737dc456d91SStefano Zampini       PetscInt j;
3738dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
3739674ae819SStefano Zampini     }
3740dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3741674ae819SStefano Zampini   } else {
3742dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3743dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
3744674ae819SStefano Zampini     }
3745674ae819SStefano Zampini   }
3746dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
3747dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
3748674ae819SStefano Zampini   PetscFunctionReturn(0);
3749674ae819SStefano Zampini }
37509a7d3425SStefano Zampini 
37519a7d3425SStefano Zampini #undef __FUNCT__
37529a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
37539a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
37549a7d3425SStefano Zampini {
37559a7d3425SStefano Zampini   PetscInt       i,j;
37569a7d3425SStefano Zampini   PetscScalar    *alphas;
37579a7d3425SStefano Zampini   PetscErrorCode ierr;
37589a7d3425SStefano Zampini 
37599a7d3425SStefano Zampini   PetscFunctionBegin;
37609a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
3761785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
37629a7d3425SStefano Zampini   for (i=0;i<n;i++) {
37639a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
37649a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
37659a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
37669a7d3425SStefano Zampini   }
37679a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
37689a7d3425SStefano Zampini   PetscFunctionReturn(0);
37699a7d3425SStefano Zampini }
37709a7d3425SStefano Zampini 
3771e7931f94SStefano Zampini #undef __FUNCT__
377270cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
3773b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
3774e7931f94SStefano Zampini {
377552e5ac9dSStefano Zampini   IS             ranks_send_to;
3776e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
3777e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
377852e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
377952e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
37803837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
37812b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
3782e7931f94SStefano Zampini   PetscSubcomm   subcomm;
378352e5ac9dSStefano Zampini   PetscErrorCode ierr;
3784a57a6d2fSStefano Zampini 
3785e7931f94SStefano Zampini   PetscFunctionBegin;
37862b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
37872b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
37882b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
3789e7931f94SStefano Zampini 
3790e7931f94SStefano Zampini   /* Get info on mapping */
37913bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
37923bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3793e7931f94SStefano Zampini 
3794e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
3795785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
3796e7931f94SStefano Zampini   xadj[0] = 0;
3797e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
3798785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
3799785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
3800e7931f94SStefano Zampini 
38012b510759SStefano Zampini   if (threshold) {
3802d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
38032b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3804d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3805d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3806d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3807d023bfaeSStefano Zampini         xadj_count++;
3808e7931f94SStefano Zampini       }
3809e7931f94SStefano Zampini     }
3810d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3811c8587f34SStefano Zampini   } else {
3812e7931f94SStefano Zampini     if (xadj[1]) {
3813e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3814e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3815c8587f34SStefano Zampini     }
3816e7931f94SStefano Zampini   }
38173bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3818e7931f94SStefano Zampini   if (use_square) {
3819e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3820e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3821e7931f94SStefano Zampini     }
3822e7931f94SStefano Zampini   }
3823e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3824e7931f94SStefano Zampini 
38253837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3826e7931f94SStefano Zampini 
3827e7931f94SStefano Zampini   /*
3828e7931f94SStefano Zampini     Restrict work on active processes only.
3829e7931f94SStefano Zampini   */
3830e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3831e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3832e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
38332b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3834d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3835e7931f94SStefano Zampini   if (color) {
3836e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3837e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3838e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3839c8587f34SStefano Zampini   } else {
384052e5ac9dSStefano Zampini     Mat             subdomain_adj;
384152e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
384252e5ac9dSStefano Zampini     MatPartitioning partitioner;
384352e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
384452e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
3845b0c7d250SStefano Zampini     PetscBool       aggregate;
3846b0c7d250SStefano Zampini 
3847306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
3848785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3849e7931f94SStefano Zampini     prank = rank;
3850306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
38518002ef2cSStefano Zampini     /*
3852e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3853e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3854c8587f34SStefano Zampini     }
38558002ef2cSStefano Zampini     */
3856e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3857e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3858c8587f34SStefano Zampini     }
3859e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3860b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
3861b0c7d250SStefano Zampini     if (aggregate) {
3862b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
3863b0c7d250SStefano Zampini       PetscMPIInt nrank;
3864b0c7d250SStefano Zampini       PetscScalar *vals;
3865b0c7d250SStefano Zampini 
3866b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
3867b0c7d250SStefano Zampini       lrows = 0;
3868b0c7d250SStefano Zampini       if (nrank<redprocs) {
3869b0c7d250SStefano Zampini         lrows = size/redprocs;
3870b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
3871b0c7d250SStefano Zampini       }
38725fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
3873b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
3874b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3875b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3876b0c7d250SStefano Zampini       row = nrank;
3877b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
3878b0c7d250SStefano Zampini       cols = adjncy;
3879b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
3880b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
3881b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
3882b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3883b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
388452e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
388552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
388652e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3887b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
3888b0c7d250SStefano Zampini     } else {
3889306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
3890b0c7d250SStefano Zampini     }
389122b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3892e7931f94SStefano Zampini 
3893e7931f94SStefano Zampini     /* Partition */
3894306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
3895e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3896e7931f94SStefano Zampini     if (use_vwgt) {
38973837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3898e7931f94SStefano Zampini       v_wgt[0] = local_size;
3899e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3900c8587f34SStefano Zampini     }
390128143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
390228143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3903e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3904e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
390522b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3906e7931f94SStefano Zampini 
390752e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
390852e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
390952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
391052e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3911b0c7d250SStefano Zampini     if (!redprocs) {
3912b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
391328143c3dSStefano Zampini     } else {
3914b0c7d250SStefano Zampini       PetscInt    idxs[1];
3915b0c7d250SStefano Zampini       PetscMPIInt tag;
3916b0c7d250SStefano Zampini       MPI_Request *reqs;
3917b0c7d250SStefano Zampini 
3918b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
3919b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
3920b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
3921b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
392228143c3dSStefano Zampini       }
3923b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
3924b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3925b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
3926b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
3927e7931f94SStefano Zampini     }
392852e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3929e7931f94SStefano Zampini     /* clean up */
3930e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
393152e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
3932e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3933e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3934e7931f94SStefano Zampini   }
3935e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3936e7931f94SStefano Zampini 
3937e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3938e7931f94SStefano Zampini   i = 1;
3939e7931f94SStefano Zampini   if (color) i=0;
3940e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3941e7931f94SStefano Zampini   /* get back IS */
3942e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3943e7931f94SStefano Zampini   PetscFunctionReturn(0);
3944e7931f94SStefano Zampini }
3945e7931f94SStefano Zampini 
3946e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3947e7931f94SStefano Zampini 
3948e7931f94SStefano Zampini #undef __FUNCT__
3949e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
395053a05cb3SStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, PetscBool restrict_full, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
3951e7931f94SStefano Zampini {
395270cf5478SStefano Zampini   Mat                    local_mat;
3953e7931f94SStefano Zampini   IS                     is_sends_internal;
39549d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
395528143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
39569d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3957e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3958e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3959e7931f94SStefano Zampini   const PetscInt*        is_indices;
3960e7931f94SStefano Zampini   MatType                new_local_type;
3961e7931f94SStefano Zampini   /* buffers */
3962e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
396328143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
39649d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3965e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3966e7931f94SStefano Zampini   /* MPI */
396728143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
396828143c3dSStefano Zampini   PetscSubcomm           subcomm;
3969e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
397028143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
397128143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
397228143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
397328143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
397428143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3975e7931f94SStefano Zampini   PetscErrorCode         ierr;
3976e7931f94SStefano Zampini 
3977e7931f94SStefano Zampini   PetscFunctionBegin;
397828143c3dSStefano Zampini   /* TODO: add missing checks */
397928143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
398028143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
398128143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
398228143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3983e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
398428143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3985e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3986e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3987e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3988e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3989e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
399028143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
399170cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
399270cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
399328143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
399470cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
399570cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
399670cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
399770cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
399870cf5478SStefano Zampini   }
3999e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
4000e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
4001e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
4002e7931f94SStefano Zampini   if (!is_sends) {
400328143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
4004b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
4005c8587f34SStefano Zampini   } else {
4006e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
4007e7931f94SStefano Zampini     is_sends_internal = is_sends;
4008c8587f34SStefano Zampini   }
4009e7931f94SStefano Zampini 
4010e7931f94SStefano Zampini   /* get comm */
4011a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4012e7931f94SStefano Zampini 
4013e7931f94SStefano Zampini   /* compute number of sends */
4014e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4015e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4016e7931f94SStefano Zampini 
4017e7931f94SStefano Zampini   /* compute number of receives */
4018e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4019785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4020e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4021e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4022e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4023e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4024e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
4025e7931f94SStefano Zampini 
402628143c3dSStefano Zampini   /* restrict comm if requested */
402728143c3dSStefano Zampini   subcomm = 0;
402828143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
402928143c3dSStefano Zampini   if (restrict_comm) {
4030779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
4031779c1cceSStefano Zampini 
403228143c3dSStefano Zampini     color = 0;
403353a05cb3SStefano Zampini     if (restrict_full) {
403453a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
403553a05cb3SStefano Zampini     } else {
403653a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
403753a05cb3SStefano Zampini     }
403828143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
403928143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
404028143c3dSStefano Zampini     /* check if reuse has been requested */
404128143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
404228143c3dSStefano Zampini       if (*mat_n) {
404328143c3dSStefano Zampini         PetscMPIInt subcommsize2;
404428143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
404528143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
404628143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
404728143c3dSStefano Zampini       } else {
404828143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
404928143c3dSStefano Zampini       }
405028143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
4051779c1cceSStefano Zampini       PetscMPIInt rank;
4052779c1cceSStefano Zampini 
4053779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
405428143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
405528143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
405628143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4057306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
405828143c3dSStefano Zampini     }
405928143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
406028143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
406128143c3dSStefano Zampini   } else {
406228143c3dSStefano Zampini     comm_n = comm;
406328143c3dSStefano Zampini   }
406428143c3dSStefano Zampini 
4065e7931f94SStefano Zampini   /* prepare send/receive buffers */
4066785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4067e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4068785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4069e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
407028143c3dSStefano Zampini   if (nis) {
4071854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
407228143c3dSStefano Zampini   }
4073e7931f94SStefano Zampini 
407428143c3dSStefano Zampini   /* Get data from local matrices */
4075e7931f94SStefano Zampini   if (!isdense) {
4076a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4077e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4078e7931f94SStefano Zampini     /*
4079e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4080e7931f94SStefano Zampini        send_buffer_idxs should contain:
4081e7931f94SStefano Zampini        - MatType_PRIVATE type
4082e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4083e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4084e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4085e7931f94SStefano Zampini     */
4086e7931f94SStefano Zampini   } else {
4087e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
40883bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4089854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4090e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4091e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
40923bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4093e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
40943bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4095e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4096e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4097e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4098e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4099c8587f34SStefano Zampini     }
4100c8587f34SStefano Zampini   }
4101e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
410228143c3dSStefano Zampini   /* additional is (if any) */
410328143c3dSStefano Zampini   if (nis) {
410428143c3dSStefano Zampini     PetscMPIInt psum;
410528143c3dSStefano Zampini     PetscInt j;
410628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
410728143c3dSStefano Zampini       PetscInt plen;
410828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
410928143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
411028143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
411128143c3dSStefano Zampini     }
4112854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
411328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
411428143c3dSStefano Zampini       PetscInt plen;
411528143c3dSStefano Zampini       const PetscInt *is_array_idxs;
411628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
411728143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
411828143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
411928143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
412028143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
412128143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
412228143c3dSStefano Zampini     }
412328143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
412428143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
412528143c3dSStefano Zampini     }
412628143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
412728143c3dSStefano Zampini   }
412828143c3dSStefano Zampini 
4129e7931f94SStefano Zampini   buf_size_idxs = 0;
4130e7931f94SStefano Zampini   buf_size_vals = 0;
413128143c3dSStefano Zampini   buf_size_idxs_is = 0;
4132e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4133e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4134e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
413528143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4136e7931f94SStefano Zampini   }
4137785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4138785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
413995ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4140e7931f94SStefano Zampini 
4141e7931f94SStefano Zampini   /* get new tags for clean communications */
4142e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4143e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
414428143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4145e7931f94SStefano Zampini 
4146e7931f94SStefano Zampini   /* allocate for requests */
4147785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4148785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
414995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4150785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4151785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
415295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4153e7931f94SStefano Zampini 
4154e7931f94SStefano Zampini   /* communications */
4155e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4156e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
415728143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4158e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4159e7931f94SStefano Zampini     source_dest = onodes[i];
4160e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4161e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4162e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4163e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
416428143c3dSStefano Zampini     if (nis) {
416528143c3dSStefano 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);
416628143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
416728143c3dSStefano Zampini     }
4168e7931f94SStefano Zampini   }
4169e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4170e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4171e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4172e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
417328143c3dSStefano Zampini     if (nis) {
417428143c3dSStefano 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);
417528143c3dSStefano Zampini     }
4176e7931f94SStefano Zampini   }
4177e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4178e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4179e7931f94SStefano Zampini 
4180e7931f94SStefano Zampini   /* assemble new l2g map */
4181e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4182e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
41839d30be91SStefano Zampini   new_local_rows = 0;
4184e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
41859d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4186e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4187e7931f94SStefano Zampini   }
41889d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4189e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
41909d30be91SStefano Zampini   new_local_rows = 0;
4191e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
41929d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
41939d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4194e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4195e7931f94SStefano Zampini   }
41969d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
41979d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4198e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4199e7931f94SStefano Zampini 
4200e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4201e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4202e7931f94SStefano 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) */
4203e7931f94SStefano Zampini   if (n_recvs) {
420428143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4205e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4206e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4207e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4208e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4209e7931f94SStefano Zampini         break;
4210e7931f94SStefano Zampini       }
4211e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4212e7931f94SStefano Zampini     }
4213e7931f94SStefano Zampini     switch (new_local_type_private) {
421428143c3dSStefano Zampini       case MATDENSE_PRIVATE:
421528143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4216e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4217e7931f94SStefano Zampini           bs = 1;
421828143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
421928143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
422028143c3dSStefano Zampini           bs = 1;
422128143c3dSStefano Zampini         }
4222e7931f94SStefano Zampini         break;
4223e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4224e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4225e7931f94SStefano Zampini         bs = 1;
4226e7931f94SStefano Zampini         break;
4227e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4228e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4229e7931f94SStefano Zampini         break;
4230e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4231e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4232e7931f94SStefano Zampini         break;
4233e7931f94SStefano Zampini       default:
42349d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4235e7931f94SStefano Zampini         break;
4236e7931f94SStefano Zampini     }
423728143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
423828143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
423928143c3dSStefano Zampini     bs = 1;
4240e7931f94SStefano Zampini   }
4241e7931f94SStefano Zampini 
424270cf5478SStefano Zampini   /* create MATIS object if needed */
424370cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4244e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4245e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
424670cf5478SStefano Zampini   } else {
424770cf5478SStefano Zampini     /* it also destroys the local matrices */
424870cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
424970cf5478SStefano Zampini   }
425070cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4251e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
42529d30be91SStefano Zampini 
42539d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
42549d30be91SStefano Zampini 
42559d30be91SStefano Zampini   /* Global to local map of received indices */
42569d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
42579d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
42589d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
42599d30be91SStefano Zampini 
42609d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
42619d30be91SStefano Zampini   buf_size_idxs = 0;
42629d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
42639d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
42649d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
42659d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
42669d30be91SStefano Zampini   }
42679d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
42689d30be91SStefano Zampini 
42699d30be91SStefano Zampini   /* set preallocation */
42709d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
42719d30be91SStefano Zampini   if (!newisdense) {
42729d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
42739d30be91SStefano Zampini 
42749d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
42759d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
42769d30be91SStefano Zampini     if (n_recvs) {
42779d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
42789d30be91SStefano Zampini     }
42799d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
42809d30be91SStefano Zampini       PetscInt j;
42819d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
42829d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
42839d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
42849d30be91SStefano Zampini         }
42859d30be91SStefano Zampini       } else {
42869d30be91SStefano Zampini         /* TODO */
42879d30be91SStefano Zampini       }
42889d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
42899d30be91SStefano Zampini     }
42909d30be91SStefano Zampini     if (new_local_nnz) {
42919d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
42929d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
42939d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
42949d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
42959d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
42969d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
42979d30be91SStefano Zampini     } else {
42989d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
42999d30be91SStefano Zampini     }
43009d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
43019d30be91SStefano Zampini   } else {
43029d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
43039d30be91SStefano Zampini   }
4304e7931f94SStefano Zampini 
4305e7931f94SStefano Zampini   /* set values */
4306e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
43079d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
4308e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4309e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
4310e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
43119d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
4312e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4313e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4314e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
431528143c3dSStefano Zampini     } else {
431628143c3dSStefano Zampini       /* TODO */
4317e7931f94SStefano Zampini     }
4318e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4319e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
4320e7931f94SStefano Zampini   }
4321e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4322e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
432370cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
432470cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
43259d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
43269d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
4327e7931f94SStefano Zampini 
4328dfd14d43SStefano Zampini #if 0
432928143c3dSStefano Zampini   if (!restrict_comm) { /* check */
4330e7931f94SStefano Zampini     Vec       lvec,rvec;
4331e7931f94SStefano Zampini     PetscReal infty_error;
4332e7931f94SStefano Zampini 
43332a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
4334e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
4335e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
4336e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
433770cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
4338e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4339e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
4340e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
4341e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
4342e7931f94SStefano Zampini   }
434328143c3dSStefano Zampini #endif
4344e7931f94SStefano Zampini 
434528143c3dSStefano Zampini   /* assemble new additional is (if any) */
434628143c3dSStefano Zampini   if (nis) {
434728143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
434828143c3dSStefano Zampini 
434928143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4350854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
435128143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
435228143c3dSStefano Zampini     psum = 0;
435328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
435428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
435528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
435628143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
435728143c3dSStefano Zampini         psum += plen;
435828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
435928143c3dSStefano Zampini       }
436028143c3dSStefano Zampini     }
4361854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
4362854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
436328143c3dSStefano Zampini     for (i=1;i<nis;i++) {
436428143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
436528143c3dSStefano Zampini     }
436628143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
436728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
436828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
436928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
437028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
437128143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
437228143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
437328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
437428143c3dSStefano Zampini       }
437528143c3dSStefano Zampini     }
437628143c3dSStefano Zampini     for (i=0;i<nis;i++) {
437728143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
437828143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
437928143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
438028143c3dSStefano Zampini     }
438128143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
438228143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
438328143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
438428143c3dSStefano Zampini   }
4385e7931f94SStefano Zampini   /* free workspace */
438628143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4387e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4388e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4389e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4390e7931f94SStefano Zampini   if (isdense) {
4391e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4392e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4393e7931f94SStefano Zampini   } else {
4394e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4395e7931f94SStefano Zampini   }
439628143c3dSStefano Zampini   if (nis) {
439728143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
439828143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
439928143c3dSStefano Zampini   }
4400e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4401e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
440228143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4403e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4404e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
440528143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4406e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4407e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4408e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4409e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4410e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
441128143c3dSStefano Zampini   if (nis) {
441228143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
441328143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
441428143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
441528143c3dSStefano Zampini   }
441628143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
441728143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
441828143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
441928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
442028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
442128143c3dSStefano Zampini     }
442253a05cb3SStefano Zampini     *mat_n = NULL;
442328143c3dSStefano Zampini   }
4424e7931f94SStefano Zampini   PetscFunctionReturn(0);
4425e7931f94SStefano Zampini }
4426a57a6d2fSStefano Zampini 
442712edc857SStefano Zampini /* temporary hack into ksp private data structure */
4428af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
442912edc857SStefano Zampini 
4430c8587f34SStefano Zampini #undef __FUNCT__
4431c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4432c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4433c8587f34SStefano Zampini {
4434c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4435c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
443620a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
44379881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
443820a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
44396e683305SStefano Zampini   IS                     coarse_is,*isarray;
44406e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
44416e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
4442f9eb5b7dSStefano Zampini   PC                     pc_temp;
4443c8587f34SStefano Zampini   PCType                 coarse_pc_type;
4444c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
4445f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
44464f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
44476e683305SStefano Zampini   Mat                    t_coarse_mat_is;
44486e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
44496e683305SStefano Zampini   PetscMPIInt            all_procs;
445074e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
445168457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
445222bc73bbSStefano Zampini   PetscScalar            *array;
44539881197aSStefano Zampini   PetscErrorCode         ierr;
4454fdc09c96SStefano Zampini 
4455c8587f34SStefano Zampini   PetscFunctionBegin;
4456c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
445768457ee5SStefano 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 */
4458fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
44595a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
4460fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
4461f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4462f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4463f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
4464fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
446551bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
446651bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4467dc4bcba2SStefano Zampini         PC        pc;
4468dc4bcba2SStefano Zampini         PetscBool isbddc;
4469dc4bcba2SStefano Zampini 
4470dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
4471dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4472dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4473dc4bcba2SStefano Zampini         if (isbddc) {
4474dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4475dc4bcba2SStefano Zampini         }
4476727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4477fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
4478fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
4479fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
4480f4ddd8eeSStefano Zampini       }
4481fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4482fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
4483f4ddd8eeSStefano Zampini     }
448470cf5478SStefano Zampini     /* reset any subassembling information */
448570cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
44866e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
44876e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4488fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
4489f4ddd8eeSStefano Zampini   }
4490c8587f34SStefano Zampini 
44916e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
44922b510759SStefano Zampini   im_active = !!(pcis->n);
44932b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
44946e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
44956e683305SStefano Zampini   void_procs = all_procs-active_procs;
44966e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
449774e2c79eSStefano Zampini   redist = PETSC_FALSE;
449822bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
44996e683305SStefano Zampini     csin_ml = PETSC_TRUE;
45006e683305SStefano Zampini     ncoarse_ml = void_procs;
4501779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4502779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
45036e683305SStefano Zampini       csin_ds = PETSC_TRUE;
450418a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
450518a45a71SStefano Zampini       redist = PETSC_TRUE;
450618a45a71SStefano Zampini     } else {
45076e683305SStefano Zampini       csin_ds = PETSC_TRUE;
4508779c1cceSStefano Zampini       ncoarse_ds = active_procs;
4509779c1cceSStefano Zampini       redist = PETSC_TRUE;
451018a45a71SStefano Zampini     }
45116e683305SStefano Zampini   } else {
45126e683305SStefano Zampini     csin_ml = PETSC_FALSE;
45136e683305SStefano Zampini     ncoarse_ml = all_procs;
45146e683305SStefano Zampini     if (void_procs) {
45156e683305SStefano Zampini       csin_ds = PETSC_TRUE;
45166e683305SStefano Zampini       ncoarse_ds = void_procs;
45176e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
45186e683305SStefano Zampini     } else {
4519779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
452074e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
452174e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
452274e2c79eSStefano Zampini         redist = PETSC_TRUE;
452374e2c79eSStefano Zampini       } else {
45246e683305SStefano Zampini         csin_ds = PETSC_FALSE;
45256e683305SStefano Zampini         ncoarse_ds = all_procs;
45266e683305SStefano Zampini       }
45276e683305SStefano Zampini     }
452874e2c79eSStefano Zampini   }
45296e683305SStefano Zampini 
45306e683305SStefano Zampini   /*
45316e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
45326e683305SStefano Zampini     - we have not exceeded the number of levels requested
45336e683305SStefano Zampini     - we can actually subassemble the active processes
45346e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
45356e683305SStefano Zampini   */
45366e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
45376e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
45386e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
45396e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
45406e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4541f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
45422b510759SStefano Zampini     } else {
4543f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
4544c8587f34SStefano Zampini     }
4545c8587f34SStefano Zampini   }
45466e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
45476e683305SStefano Zampini   if (multilevel_allowed) {
45486e683305SStefano Zampini     ncoarse = ncoarse_ml;
45496e683305SStefano Zampini     csin = csin_ml;
455058da7f69SStefano Zampini     redist = PETSC_FALSE;
45516e683305SStefano Zampini   } else {
45526e683305SStefano Zampini     ncoarse = ncoarse_ds;
45536e683305SStefano Zampini     csin = csin_ds;
45546e683305SStefano Zampini   }
4555e7931f94SStefano Zampini 
4556abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
4557abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4558abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4559abbbba34SStefano Zampini 
4560abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
456122bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
456222bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
456322bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
456422bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4565b1ecc7b1SStefano Zampini #if 0
4566b9b85e73SStefano Zampini   {
4567b9b85e73SStefano Zampini     PetscViewer viewer;
4568b9b85e73SStefano Zampini     char filename[256];
4569b1ecc7b1SStefano Zampini     sprintf(filename,"local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4570b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4571b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4572b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
4573b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4574b9b85e73SStefano Zampini   }
4575b9b85e73SStefano Zampini #endif
4576e176bc59SStefano 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);
45776e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
45786e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45796e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4580abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4581abbbba34SStefano Zampini 
45826e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
45836e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
45846e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
45856e683305SStefano Zampini     const PetscInt         *idxs;
45866e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
45876e683305SStefano Zampini 
45886e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
45890be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
45906e683305SStefano Zampini     /* allocate space for temporary storage */
4591854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4592854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
45936e683305SStefano Zampini     /* allocate for IS array */
45946e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
45956e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
45966e683305SStefano Zampini     nis = nisdofs + nisneu;
4597854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
45986e683305SStefano Zampini     /* dofs splitting */
45996e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
46006e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
46016e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
46026e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
46036e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
46046e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
46056e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
46066e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
46076e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
46086e683305SStefano Zampini     }
46096e683305SStefano Zampini     /* neumann boundaries */
46106e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
46116e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
46126e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
46136e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
46146e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
46156e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
46166e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
46176e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
46186e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
46196e683305SStefano Zampini     }
46206e683305SStefano Zampini     /* free memory */
46216e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
46226e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
46236e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
46246e683305SStefano Zampini   } else {
46256e683305SStefano Zampini     nis = 0;
46266e683305SStefano Zampini     nisdofs = 0;
46276e683305SStefano Zampini     nisneu = 0;
46286e683305SStefano Zampini     isarray = NULL;
46296e683305SStefano Zampini   }
46306e683305SStefano Zampini   /* destroy no longer needed map */
46316e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
46326e683305SStefano Zampini 
46336e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
46346e683305SStefano Zampini   coarse_mat_is = NULL;
46356e683305SStefano Zampini   if (csin) {
46366e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
463774e2c79eSStefano Zampini       if (redist) {
463874e2c79eSStefano Zampini         PetscMPIInt rank;
4639779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
464074e2c79eSStefano Zampini 
464174e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
464258da7f69SStefano Zampini         spc = active_procs/ncoarse;
464358da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
4644779c1cceSStefano Zampini         if (im_active) {
4645779c1cceSStefano Zampini           destsize = 1;
464674e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
464774e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
464874e2c79eSStefano Zampini           } else {
464974e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
465074e2c79eSStefano Zampini           }
465174e2c79eSStefano Zampini         } else {
4652779c1cceSStefano Zampini           destsize = 0;
46536e683305SStefano Zampini         }
4654779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4655779c1cceSStefano Zampini       } else if (csin_type_simple) {
46566e683305SStefano Zampini         PetscMPIInt rank;
46576e683305SStefano Zampini         PetscInt    issize,isidx;
4658779c1cceSStefano Zampini 
46596e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
46606e683305SStefano Zampini         if (im_active) {
46616e683305SStefano Zampini           issize = 1;
46626e683305SStefano Zampini           isidx = (PetscInt)rank;
46636e683305SStefano Zampini         } else {
46646e683305SStefano Zampini           issize = 0;
46656e683305SStefano Zampini           isidx = -1;
46666e683305SStefano Zampini         }
46676e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4668779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
4669b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
46706e683305SStefano Zampini       }
4671779c1cceSStefano Zampini 
4672779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
4673779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
4674779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
4675779c1cceSStefano Zampini         PetscInt *coarse_candidates;
4676779c1cceSStefano Zampini         const PetscInt* tisindices;
4677779c1cceSStefano Zampini 
4678779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
4679779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
4680779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4681779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
4682779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
4683779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
4684779c1cceSStefano Zampini           }
4685779c1cceSStefano Zampini         }
4686779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
4687779c1cceSStefano Zampini 
4688779c1cceSStefano Zampini 
46896e683305SStefano Zampini         if (pcbddc->dbg_flag) {
46906e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
46916e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
46926e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
46936e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
4694779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
46956e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
46966e683305SStefano Zampini           }
46976e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
46986e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
46996e683305SStefano Zampini         }
47006e683305SStefano Zampini         /* shift the pattern on coarse candidates */
47016e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
47026e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
4703854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
47046e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
47056e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
47066e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
47076e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
47086e683305SStefano Zampini       }
47096e683305SStefano Zampini       if (pcbddc->dbg_flag) {
47106e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47116e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
47126e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
47136e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
47146e683305SStefano Zampini       }
4715779c1cceSStefano Zampini     }
47166e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
471753a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
471853a05cb3SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,PETSC_FALSE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
471953a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
472053a05cb3SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
472153a05cb3SStefano Zampini     }
47226e683305SStefano Zampini   } else {
47236e683305SStefano Zampini     if (pcbddc->dbg_flag) {
47246e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47256e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
47266e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
47276e683305SStefano Zampini     }
47286e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
47296e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
47306e683305SStefano Zampini   }
47316e683305SStefano Zampini 
47326e683305SStefano Zampini   /* create local to global scatters for coarse problem */
473368457ee5SStefano Zampini   if (compute_vecs) {
47346e683305SStefano Zampini     PetscInt lrows;
47356e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
47366e683305SStefano Zampini     if (coarse_mat_is) {
47376e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
47386e683305SStefano Zampini     } else {
47396e683305SStefano Zampini       lrows = 0;
47406e683305SStefano Zampini     }
47416e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
47426e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
47436e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
47446e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
47456e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
47466e683305SStefano Zampini   }
47476e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
47486e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
4749c8587f34SStefano Zampini 
4750f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
4751f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
4752f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
4753f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
4754f9eb5b7dSStefano Zampini   } else {
4755f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
4756f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
4757c8587f34SStefano Zampini   }
4758c8587f34SStefano Zampini 
47596e683305SStefano Zampini   /* print some info if requested */
47606e683305SStefano Zampini   if (pcbddc->dbg_flag) {
47616e683305SStefano Zampini     if (!multilevel_allowed) {
47626e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47636e683305SStefano Zampini       if (multilevel_requested) {
47646e683305SStefano 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);
47656e683305SStefano Zampini       } else if (pcbddc->max_levels) {
47666e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
47676e683305SStefano Zampini       }
47686e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
47696e683305SStefano Zampini     }
47706e683305SStefano Zampini   }
47716e683305SStefano Zampini 
4772f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
47736e683305SStefano Zampini   if (coarse_mat_is) {
47746e683305SStefano Zampini     MatReuse coarse_mat_reuse;
47756a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
47766e683305SStefano Zampini     if (pcbddc->dbg_flag) {
47776e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
47786e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
47796e683305SStefano Zampini     }
4780f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
4781312be037SStefano Zampini       char prefix[256],str_level[16];
4782e604994aSStefano Zampini       size_t len;
47836e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
4784422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
4785c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
4786f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
47875f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
4788c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
47896e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
4790c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4791c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4792e604994aSStefano Zampini       /* prefix */
4793e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
4794e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4795e604994aSStefano Zampini       if (!pcbddc->current_level) {
4796e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4797e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
4798c8587f34SStefano Zampini       } else {
4799e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4800312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4801312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
480234d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4803312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4804e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
4805e604994aSStefano Zampini       }
4806e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
48073e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
48083e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
48093e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
48103e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
4811f9eb5b7dSStefano Zampini       /* allow user customization */
4812f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
48133e3c6dadSStefano Zampini     }
48143e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
481551bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
48163e3c6dadSStefano Zampini     if (nisdofs) {
48173e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
48183e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
48193e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
48203e3c6dadSStefano Zampini       }
48213e3c6dadSStefano Zampini     }
48223e3c6dadSStefano Zampini     if (nisneu) {
48233e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
48243e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
4825312be037SStefano Zampini     }
4826f9eb5b7dSStefano Zampini 
4827f9eb5b7dSStefano Zampini     /* get some info after set from options */
4828f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
4829f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
48304f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
48316e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
4832f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4833f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
4834f9eb5b7dSStefano Zampini     }
483539f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
48364f3a063dSStefano Zampini     if (isredundant) {
48374f3a063dSStefano Zampini       KSP inner_ksp;
48384f3a063dSStefano Zampini       PC  inner_pc;
48394f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
48404f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
48414f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
48424f3a063dSStefano Zampini     }
4843f9eb5b7dSStefano Zampini 
4844f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
4845fa7f1dd8SStefano Zampini     if (coarse_reuse) {
484681d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
4847fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
48486e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
4849fa7f1dd8SStefano Zampini     } else {
48506e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
4851fa7f1dd8SStefano Zampini     }
4852c8587f34SStefano Zampini     if (isbddc || isnn) {
485322bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
485470cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
4855b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
485622b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
48576e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
48586e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
48596e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
48606e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
486122b6e8a2SStefano Zampini           }
486270cf5478SStefano Zampini         }
486353a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
486470cf5478SStefano Zampini       } else {
486522bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
486622bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
486722bc73bbSStefano Zampini       }
486822bc73bbSStefano Zampini     } else {
48692e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
4870c8587f34SStefano Zampini     }
4871c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
4872c8587f34SStefano Zampini 
48733301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
48745a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
48753301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
48763301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
48773301b35fSStefano Zampini     }
48783301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
48793301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
48803301b35fSStefano Zampini     }
48813301b35fSStefano Zampini     if (pc->pmat->spd_set) {
48823301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
48833301b35fSStefano Zampini     }
48846e683305SStefano Zampini     /* set operators */
48855f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
48866e683305SStefano Zampini     if (pcbddc->dbg_flag) {
48876e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
48886e683305SStefano Zampini     }
48896e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
48906e683305SStefano Zampini     coarse_mat = 0;
48916e683305SStefano Zampini   }
48926e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
4893b1ecc7b1SStefano Zampini #if 0
4894b9b85e73SStefano Zampini   {
4895b9b85e73SStefano Zampini     PetscViewer viewer;
4896b9b85e73SStefano Zampini     char filename[256];
4897b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
4898b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
4899b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4900b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4901b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4902b9b85e73SStefano Zampini   }
4903b9b85e73SStefano Zampini #endif
4904c8587f34SStefano Zampini 
4905c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4906298c0119SStefano Zampini #if 0
4907c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4908c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
490998a51de6SStefano Zampini   }
4910298c0119SStefano Zampini #endif
4911b0f5fe93SStefano Zampini   /* hack */
491298a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
491398a51de6SStefano Zampini     Vec crhs,csol;
491404708bb6SStefano Zampini 
4915f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4916f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
4917f347579bSStefano Zampini     if (!csol) {
49182a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4919f9eb5b7dSStefano Zampini     }
4920f347579bSStefano Zampini     if (!crhs) {
49212a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4922f347579bSStefano Zampini     }
4923b0f5fe93SStefano Zampini   }
4924b0f5fe93SStefano Zampini 
4925b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
4926b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
4927b0f5fe93SStefano Zampini 
4928b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
4929b0f5fe93SStefano Zampini     ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-1,1.0,INSERT_VALUES);CHKERRQ(ierr);
4930b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
4931b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
4932b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4933b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4934b0f5fe93SStefano Zampini     if (coarse_mat) {
4935b0f5fe93SStefano Zampini       Vec         nullv;
4936b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
4937b0f5fe93SStefano Zampini       PetscInt    nl;
4938b0f5fe93SStefano Zampini 
4939b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
4940b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
4941b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
4942b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
4943b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
4944b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
4945b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
4946b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
4947b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
4948b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
4949b0f5fe93SStefano Zampini     }
4950b0f5fe93SStefano Zampini   }
4951b0f5fe93SStefano Zampini 
4952b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
4953b0f5fe93SStefano Zampini     PetscBool ispreonly;
4954b0f5fe93SStefano Zampini 
4955b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
4956b0f5fe93SStefano Zampini       PetscBool isnull;
4957b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
4958b0f5fe93SStefano Zampini       if (isnull) {
4959b0f5fe93SStefano Zampini         if (isbddc) {
4960b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4961b0f5fe93SStefano Zampini         } else {
4962b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
4963b0f5fe93SStefano Zampini         }
4964b0f5fe93SStefano Zampini       } else {
4965b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4966b0f5fe93SStefano Zampini       }
4967b0f5fe93SStefano Zampini     }
4968b0f5fe93SStefano Zampini     /* setup coarse ksp */
4969b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4970cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4971cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
49726e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4973c8587f34SStefano Zampini       KSP       check_ksp;
49742b510759SStefano Zampini       KSPType   check_ksp_type;
4975c8587f34SStefano Zampini       PC        check_pc;
49766e683305SStefano Zampini       Vec       check_vec,coarse_vec;
49776a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
49782b510759SStefano Zampini       PetscInt  its;
49796e683305SStefano Zampini       PetscBool compute_eigs;
49806e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
49816e683305SStefano Zampini       PetscInt  neigs;
49828e185a42SStefano Zampini       const char *prefix;
4983c8587f34SStefano Zampini 
49842b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
49856e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
4986422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
498723ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4988f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
49892b510759SStefano Zampini       if (ispreonly) {
49902b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
49916e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
49922b510759SStefano Zampini       } else {
4993cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
49946e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4995c8587f34SStefano Zampini       }
4996c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
49976e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
49986e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
49996e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
5000a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
5001a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
5002a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
5003a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
5004c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
5005c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
5006c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
5007c8587f34SStefano Zampini       /* create random vec */
50086e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
50096e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5010c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5011c8587f34SStefano Zampini       if (CoarseNullSpace) {
5012c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5013c8587f34SStefano Zampini       }
50146e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5015c8587f34SStefano Zampini       /* solve coarse problem */
50166e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5017c8587f34SStefano Zampini       if (CoarseNullSpace) {
50186e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5019c8587f34SStefano Zampini       }
5020cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
50216e683305SStefano Zampini       if (compute_eigs) {
5022854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5023854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
50246e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
50256e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
50266e683305SStefano Zampini         lambda_min = eigs_r[0];
50276e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
50286e683305SStefano Zampini           if (lambda_max>lambda_min) {
5029cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5030cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5031cbcc2c2aSStefano Zampini           }
5032c8587f34SStefano Zampini         }
5033c8587f34SStefano Zampini       }
5034cbcc2c2aSStefano Zampini 
5035c8587f34SStefano Zampini       /* check coarse problem residual error */
50366e683305SStefano Zampini       if (pcbddc->dbg_flag) {
50376e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
50386e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
50396e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5040c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
50416e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
50426e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5043c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5044779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
50456e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
50466e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
50476e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
50486e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5049b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
5050b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5051b0f5fe93SStefano Zampini         }
50526e683305SStefano Zampini         if (compute_eigs) {
50536e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
5054deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5055c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
50566e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
50576e683305SStefano 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);
50586e683305SStefano Zampini           for (i=0;i<neigs;i++) {
50596e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5060c8587f34SStefano Zampini           }
50616e683305SStefano Zampini         }
50626e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
50636e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
50646e683305SStefano Zampini       }
5065c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
50666e683305SStefano Zampini       if (compute_eigs) {
50676e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
50686e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5069c8587f34SStefano Zampini       }
50706e683305SStefano Zampini     }
50716e683305SStefano Zampini   }
5072cbcc2c2aSStefano Zampini   /* print additional info */
5073cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
50746e683305SStefano Zampini     /* waits until all processes reaches this point */
50756e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5076cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5077cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5078cbcc2c2aSStefano Zampini   }
5079cbcc2c2aSStefano Zampini 
50802b510759SStefano Zampini   /* free memory */
5081c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5082fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5083c8587f34SStefano Zampini   PetscFunctionReturn(0);
5084c8587f34SStefano Zampini }
5085674ae819SStefano Zampini 
5086f34684f1SStefano Zampini #undef __FUNCT__
5087f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5088f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5089f34684f1SStefano Zampini {
5090f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5091f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5092f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5093dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5094dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
509573be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5096dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5097f34684f1SStefano Zampini   PetscErrorCode ierr;
5098f34684f1SStefano Zampini 
5099f34684f1SStefano Zampini   PetscFunctionBegin;
5100f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
51010e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
51020e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5103727cdba6SStefano Zampini   }
5104dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
51053bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5106dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5107dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5108dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5109dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5110dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5111dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
51120e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
51130e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
51140e6343abSStefano Zampini   }
5115dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5116dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5117dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5118dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5119dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5120f34684f1SStefano Zampini 
5121f34684f1SStefano Zampini   /* check numbering */
5122f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5123019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5124dc456d91SStefano Zampini     PetscInt    i;
5125b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5126f34684f1SStefano Zampini 
5127f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5128f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5129f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
51300fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
5131019a44ceSStefano Zampini     /* counter */
5132019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5133019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5134019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5135019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5136019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5137019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5138019a44ceSStefano Zampini 
5139f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5140f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5141727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5142f34684f1SStefano Zampini     }
5143f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5144f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5145f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5146e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5147e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5148e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5149e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5150f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5151019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5152f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5153019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
5154*75c01103SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]);
5155*75c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
5156b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5157019a44ceSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a %d processes instead of %d!\n",PetscGlobalRank,i,owned,neigh);CHKERRQ(ierr);
5158f34684f1SStefano Zampini       }
5159f34684f1SStefano Zampini     }
5160019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5161b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5162f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5163f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5164f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5165f34684f1SStefano Zampini     }
5166f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5167f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5168e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5169e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5170f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5171f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5172b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5173ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5174ca8b9ea9SStefano Zampini 
5175ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
51763bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5177f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5178f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5179f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5180f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
51814bc2dc4bSStefano 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);
5182f34684f1SStefano Zampini       }
5183f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5184ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5185f34684f1SStefano Zampini     }
5186f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5187302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5188f34684f1SStefano Zampini   }
51898bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5190f34684f1SStefano Zampini   /* get back data */
5191f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5192f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5193674ae819SStefano Zampini   PetscFunctionReturn(0);
5194674ae819SStefano Zampini }
5195674ae819SStefano Zampini 
5196e456f2a8SStefano Zampini #undef __FUNCT__
5197e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5198a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5199e456f2a8SStefano Zampini {
5200e456f2a8SStefano Zampini   IS             localis_t;
5201a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5202e456f2a8SStefano Zampini   PetscScalar    *vals;
5203e456f2a8SStefano Zampini   PetscErrorCode ierr;
5204e456f2a8SStefano Zampini 
5205e456f2a8SStefano Zampini   PetscFunctionBegin;
5206a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5207e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5208854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5209e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5210e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5211a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5212a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
52131035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5214a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
52151035eff8SStefano Zampini   }
5216a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5217e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5218e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5219a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5220a7dc3881SStefano Zampini   /* now compute set in local ordering */
5221a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5222a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5223a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5224a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5225a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5226ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5227e456f2a8SStefano Zampini       lsize++;
5228e456f2a8SStefano Zampini     }
5229e456f2a8SStefano Zampini   }
5230854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5231a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5232ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5233e456f2a8SStefano Zampini       idxs[lsize++] = i;
5234e456f2a8SStefano Zampini     }
5235e456f2a8SStefano Zampini   }
5236a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5237a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5238e456f2a8SStefano Zampini   *localis = localis_t;
5239e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5240e456f2a8SStefano Zampini }
5241906d46d4SStefano Zampini 
5242906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5243906d46d4SStefano Zampini #undef __FUNCT__
5244906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5245906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5246906d46d4SStefano Zampini {
5247906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5248906d46d4SStefano Zampini   PetscErrorCode   ierr;
5249906d46d4SStefano Zampini 
5250906d46d4SStefano Zampini   PetscFunctionBegin;
5251906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5252906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5253906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5254906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5255906d46d4SStefano Zampini   PetscFunctionReturn(0);
5256906d46d4SStefano Zampini }
5257906d46d4SStefano Zampini 
5258906d46d4SStefano Zampini #undef __FUNCT__
5259906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5260906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5261906d46d4SStefano Zampini {
5262906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5263906d46d4SStefano Zampini   PetscErrorCode   ierr;
5264906d46d4SStefano Zampini 
5265906d46d4SStefano Zampini   PetscFunctionBegin;
5266906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5267906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5268906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5269906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5270906d46d4SStefano Zampini   PetscFunctionReturn(0);
5271906d46d4SStefano Zampini }
5272b96c3477SStefano Zampini 
5273b96c3477SStefano Zampini #undef __FUNCT__
5274b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
527508122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5276b96c3477SStefano Zampini {
5277a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5278b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5279b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5280a64f4aa4SStefano Zampini   Mat                 S_j;
5281b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
5282b96c3477SStefano Zampini   PetscBool           free_used_adj;
5283b96c3477SStefano Zampini   PetscErrorCode      ierr;
5284b96c3477SStefano Zampini 
5285b96c3477SStefano Zampini   PetscFunctionBegin;
5286b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
5287b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
528808122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
5289b96c3477SStefano Zampini     used_xadj = NULL;
5290b96c3477SStefano Zampini     used_adjncy = NULL;
5291b96c3477SStefano Zampini   } else {
529208122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
529308122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
529408122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
529508122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
5296b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
5297b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
5298b96c3477SStefano Zampini     } else {
52992fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
5300b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
5301b96c3477SStefano Zampini       PetscInt       nvtxs;
5302b96c3477SStefano Zampini 
53032fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
53042fffb893SStefano Zampini       if (flg_row) {
5305b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
5306b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
5307b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
5308b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
53092fffb893SStefano Zampini       } else {
53102fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
53112fffb893SStefano Zampini         used_xadj = NULL;
53122fffb893SStefano Zampini         used_adjncy = NULL;
53132fffb893SStefano Zampini       }
53142fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5315b96c3477SStefano Zampini     }
5316b96c3477SStefano Zampini   }
5317d5574798SStefano Zampini 
5318d5574798SStefano Zampini   /* setup sub_schurs data */
5319a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5320a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
5321a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
5322a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
532306a4e24aSStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,NULL,S_j,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->faster_deluxe,pcbddc->adaptive_selection,PETSC_FALSE,PETSC_FALSE);CHKERRQ(ierr);
5324a64f4aa4SStefano Zampini   } else {
53256816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
532604708bb6SStefano Zampini     PetscBool isseqaij;
53275feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
53285feab87aSStefano Zampini       PetscInt n_vertices;
53295feab87aSStefano Zampini 
53305feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
53312034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
53325feab87aSStefano Zampini     }
533304708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
533404708bb6SStefano Zampini     if (!isseqaij) {
533504708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
533604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
533704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
533804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
533904708bb6SStefano Zampini       } else {
534004708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
534104708bb6SStefano Zampini       }
534204708bb6SStefano Zampini     }
534306a4e24aSStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,pcbddc->local_mat,S_j,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->faster_deluxe,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point);CHKERRQ(ierr);
5344a64f4aa4SStefano Zampini   }
5345a64f4aa4SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5346b96c3477SStefano Zampini 
5347b96c3477SStefano Zampini   /* free adjacency */
5348b96c3477SStefano Zampini   if (free_used_adj) {
5349b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
5350b96c3477SStefano Zampini   }
5351b96c3477SStefano Zampini   PetscFunctionReturn(0);
5352b96c3477SStefano Zampini }
5353b96c3477SStefano Zampini 
5354b96c3477SStefano Zampini #undef __FUNCT__
5355b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
535608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
5357b96c3477SStefano Zampini {
5358b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5359b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5360b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5361b96c3477SStefano Zampini   PCBDDCGraph         graph;
5362b96c3477SStefano Zampini   PetscErrorCode      ierr;
5363b96c3477SStefano Zampini 
5364b96c3477SStefano Zampini   PetscFunctionBegin;
5365b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
536608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
53673301b35fSStefano Zampini     IS       verticesIS,verticescomm;
53683301b35fSStefano Zampini     PetscInt vsize,*idxs;
5369b96c3477SStefano Zampini 
5370b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
53713301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
53723301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
53733301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
53743301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
53753301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
5376b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
53777fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
53783301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
53793301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
5380b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5381b96c3477SStefano Zampini /*
5382b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
5383b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5384b96c3477SStefano Zampini     }
5385b96c3477SStefano Zampini */
5386b96c3477SStefano Zampini   } else {
5387b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
5388b96c3477SStefano Zampini   }
5389b96c3477SStefano Zampini 
5390b96c3477SStefano Zampini   /* sub_schurs init */
5391a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
5392a64f4aa4SStefano Zampini 
5393b96c3477SStefano Zampini   /* free graph struct */
539408122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
5395b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
5396b96c3477SStefano Zampini   }
5397b96c3477SStefano Zampini   PetscFunctionReturn(0);
5398b96c3477SStefano Zampini }
5399fa34dd3eSStefano Zampini 
5400fa34dd3eSStefano Zampini #undef __FUNCT__
5401fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
5402fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
5403fa34dd3eSStefano Zampini {
5404fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5405fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5406fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
5407fa34dd3eSStefano Zampini 
5408fa34dd3eSStefano Zampini   PetscFunctionBegin;
5409fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
5410fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
5411fa34dd3eSStefano Zampini     Mat            S_j,B0=NULL,B0_B=NULL;
5412fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
5413*75c01103SStefano Zampini     PetscScalar    p0_check,*array,*array2;
5414*75c01103SStefano Zampini     PetscReal      norm;
5415fa34dd3eSStefano Zampini     PetscInt       i;
5416fa34dd3eSStefano Zampini 
5417fa34dd3eSStefano Zampini     /* B0 and B0_B */
5418fa34dd3eSStefano Zampini     if (zerodiag) {
5419fa34dd3eSStefano Zampini       IS       dummy;
5420fa34dd3eSStefano Zampini       PetscInt ii[2];
5421fa34dd3eSStefano Zampini 
5422fa34dd3eSStefano Zampini       ii[0] = 0;
5423fa34dd3eSStefano Zampini       ii[1] = pcbddc->B0_ncol;
5424fa34dd3eSStefano Zampini       ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,1,pcis->n,ii,pcbddc->B0_cols,pcbddc->B0_vals,&B0);CHKERRQ(ierr);
5425fa34dd3eSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&dummy);CHKERRQ(ierr);
5426fa34dd3eSStefano Zampini       ierr = MatGetSubMatrix(B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
5427fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
5428fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
5429fa34dd3eSStefano Zampini     }
5430fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
5431fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
5432fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
5433fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5434fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5435fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5436fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5437fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
5438fa34dd3eSStefano Zampini     /* S_j */
5439fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5440fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
5441fa34dd3eSStefano Zampini 
5442fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
5443fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
5444fa34dd3eSStefano Zampini     /* continuous in primal space */
5445fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
5446fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5447fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5448fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5449fa34dd3eSStefano Zampini     if (zerodiag) {
5450fa34dd3eSStefano Zampini       p0_check = array[pcbddc->local_primal_size-1];
5451fa34dd3eSStefano Zampini     } else {
5452fa34dd3eSStefano Zampini       p0_check = 0;
5453fa34dd3eSStefano Zampini     }
5454fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5455fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5456fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5457fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5458fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5459fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5460fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
5461fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
5462fa34dd3eSStefano Zampini 
5463fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
5464fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
5465fa34dd3eSStefano Zampini     /* local with Schur */
5466fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
5467fa34dd3eSStefano Zampini     if (zerodiag) {
5468fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
5469fa34dd3eSStefano Zampini       array[0] = p0_check;
5470fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5471fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5472fa34dd3eSStefano Zampini     }
5473fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
5474fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5475fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5476fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5477fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5478fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
5479fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5480fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5481fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
5482fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5483fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5484fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5485fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5486fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5487fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
5488fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
5489fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5490fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5491fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5492fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5493fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5494fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5495fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
5496fa34dd3eSStefano Zampini     if (zerodiag) {
5497fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
5498fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
5499fa34dd3eSStefano Zampini       pcbddc->benign_p0 = array[0];
5500fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5501fa34dd3eSStefano Zampini     } else {
5502fa34dd3eSStefano Zampini       pcbddc->benign_p0 = 0.;
5503fa34dd3eSStefano Zampini     }
5504fa34dd3eSStefano Zampini     /* BDDC */
5505fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
5506fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
5507fa34dd3eSStefano Zampini 
5508fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
5509fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
5510fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
5511fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
5512fa34dd3eSStefano Zampini     if (pcbddc->benign_p0_lidx >= 0) {
5513fa34dd3eSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0 error is %1.4e\n",PetscGlobalRank,PetscAbsScalar(pcbddc->benign_p0-p0_check));
5514fa34dd3eSStefano Zampini     }
5515fa34dd3eSStefano Zampini 
5516fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
5517fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
5518fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
5519fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5520fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0);CHKERRQ(ierr);
5521fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
5522fa34dd3eSStefano Zampini   }
5523fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
5524fa34dd3eSStefano Zampini }
5525