xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision b0f5fe9377c0bb7ceae821c2544bbd08938c982b)
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);
745408967cSStefano Zampini   if (pcbddc->benign_p0_gidx >=0 && 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;
86*b0f5fe93SStefano Zampini   PetscInt       nz,n;
87*b0f5fe93SStefano 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;
142*b0f5fe93SStefano 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.;
173*b0f5fe93SStefano 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.;
178*b0f5fe93SStefano 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);
192*b0f5fe93SStefano Zampini   } else { /* if nz == 0, destroy local IS */
193*b0f5fe93SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
194339f8db1SStefano Zampini   }
195*b0f5fe93SStefano Zampini 
196*b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
197*b0f5fe93SStefano Zampini   ierr = MatGetLocalSize(pcbddc->benign_original_mat,&n,NULL);CHKERRQ(ierr);
198*b0f5fe93SStefano Zampini   have_null = PETSC_TRUE;
199*b0f5fe93SStefano Zampini   if (!zerodiag && n) have_null = PETSC_FALSE;
200*b0f5fe93SStefano 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) {
2232964fefecSStefano Zampini     Vec rhs,sol;
2233964fefecSStefano Zampini 
2234964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2235964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
223612edc857SStefano Zampini     if (applytranspose) {
2237964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
223812edc857SStefano Zampini     } else {
2239964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
224012edc857SStefano Zampini     }
224112edc857SStefano Zampini   }
2242674ae819SStefano Zampini 
2243674ae819SStefano Zampini   /* Local solution on R nodes */
224480677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
224580677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
22469f00e9b4SStefano Zampini   }
2247674ae819SStefano Zampini 
22489f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
22499f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
225012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2251674ae819SStefano Zampini 
2252674ae819SStefano Zampini   /* Sum contributions from two levels */
2253dc359a40SStefano Zampini   if (applytranspose) {
2254dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2255dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2256dc359a40SStefano Zampini   } else {
2257674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
22588eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2259dc359a40SStefano Zampini   }
2260efc2fbd9SStefano Zampini   /* store p0 */
2261c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
2262efc2fbd9SStefano Zampini     PetscScalar *array;
2263efc2fbd9SStefano Zampini 
2264efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2265efc2fbd9SStefano Zampini     pcbddc->benign_p0 = array[pcbddc->local_primal_size-1];
2266efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2267efc2fbd9SStefano Zampini   }
2268674ae819SStefano Zampini   PetscFunctionReturn(0);
2269674ae819SStefano Zampini }
2270674ae819SStefano Zampini 
2271674ae819SStefano Zampini #undef __FUNCT__
2272674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
227312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2274674ae819SStefano Zampini {
2275674ae819SStefano Zampini   PetscErrorCode ierr;
2276674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
227758da7f69SStefano Zampini   PetscScalar    *array;
227812edc857SStefano Zampini   Vec            from,to;
2279674ae819SStefano Zampini 
2280674ae819SStefano Zampini   PetscFunctionBegin;
228112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
228212edc857SStefano Zampini     from = pcbddc->coarse_vec;
228312edc857SStefano Zampini     to = pcbddc->vec1_P;
228412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
228512edc857SStefano Zampini       Vec tvec;
228658da7f69SStefano Zampini 
228758da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
228858da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
228912edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
229058da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
229158da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
229258da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
229312edc857SStefano Zampini     }
229412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
229512edc857SStefano Zampini     from = pcbddc->vec1_P;
229612edc857SStefano Zampini     to = pcbddc->coarse_vec;
229712edc857SStefano Zampini   }
229812edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2299674ae819SStefano Zampini   PetscFunctionReturn(0);
2300674ae819SStefano Zampini }
2301674ae819SStefano Zampini 
2302674ae819SStefano Zampini #undef __FUNCT__
2303674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
230412edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
2305674ae819SStefano Zampini {
2306674ae819SStefano Zampini   PetscErrorCode ierr;
2307674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
230858da7f69SStefano Zampini   PetscScalar    *array;
230912edc857SStefano Zampini   Vec            from,to;
2310674ae819SStefano Zampini 
2311674ae819SStefano Zampini   PetscFunctionBegin;
231212edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
231312edc857SStefano Zampini     from = pcbddc->coarse_vec;
231412edc857SStefano Zampini     to = pcbddc->vec1_P;
231512edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
231612edc857SStefano Zampini     from = pcbddc->vec1_P;
231712edc857SStefano Zampini     to = pcbddc->coarse_vec;
231812edc857SStefano Zampini   }
231912edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
232012edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
232112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
232212edc857SStefano Zampini       Vec tvec;
232358da7f69SStefano Zampini 
232412edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
232558da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
232658da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
232758da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
232858da7f69SStefano Zampini     }
232958da7f69SStefano Zampini   } else {
233058da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
233158da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
233212edc857SStefano Zampini     }
233312edc857SStefano Zampini   }
2334674ae819SStefano Zampini   PetscFunctionReturn(0);
2335674ae819SStefano Zampini }
2336674ae819SStefano Zampini 
2337984c4197SStefano Zampini /* uncomment for testing purposes */
2338984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
2339674ae819SStefano Zampini #undef __FUNCT__
2340674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
2341674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
2342674ae819SStefano Zampini {
2343674ae819SStefano Zampini   PetscErrorCode    ierr;
2344674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
2345674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
2346674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
2347984c4197SStefano Zampini   /* one and zero */
2348984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
2349984c4197SStefano Zampini   /* space to store constraints and their local indices */
23509162d606SStefano Zampini   PetscScalar       *constraints_data;
23519162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
23529162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
23539162d606SStefano Zampini   PetscInt          *constraints_n;
2354984c4197SStefano Zampini   /* iterators */
2355b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
2356984c4197SStefano Zampini   /* BLAS integers */
2357e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
2358e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2359c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2360727cdba6SStefano Zampini   /* reuse */
23610e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
23620e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2363984c4197SStefano Zampini   /* change of basis */
2364b3d85658SStefano Zampini   PetscBool         qr_needed;
23659162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
2366984c4197SStefano Zampini   /* auxiliary stuff */
236764efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
23688a0068c3SStefano Zampini   PetscInt          ncc;
2369984c4197SStefano Zampini   /* some quantities */
237045a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2371a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2372984c4197SStefano Zampini 
2373674ae819SStefano Zampini   PetscFunctionBegin;
23748e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
23758e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
23768e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2377088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
2378088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
23790e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
23800e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
23810e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
23820e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
23830e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2384088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2385cf5a6209SStefano Zampini 
2386cf5a6209SStefano Zampini   /* print some info */
2387cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
2388cf5a6209SStefano Zampini     IS       vertices;
2389cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
2390cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2391cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2392cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2393cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2394cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2395cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2396fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2397fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2398cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2399cf5a6209SStefano Zampini   }
2400cf5a6209SStefano Zampini 
2401cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
24029162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
2403cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
2404cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
2405cf5a6209SStefano Zampini     Vec          *localnearnullsp;
2406cf5a6209SStefano Zampini     PetscScalar  *array;
2407cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2408cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
2409674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
2410b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
2411674ae819SStefano Zampini     PetscScalar  *work;
2412674ae819SStefano Zampini     PetscReal    *singular_vals;
2413674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2414674ae819SStefano Zampini     PetscReal    *rwork;
2415674ae819SStefano Zampini #endif
2416674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2417674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
2418674ae819SStefano Zampini #else
2419964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
2420964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
2421674ae819SStefano Zampini #endif
2422674ae819SStefano Zampini 
2423674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
2424d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2425d06fc5fdSStefano Zampini     /* free unneeded index sets */
2426d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
2427d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2428674ae819SStefano Zampini     }
2429d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
2430d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
2431d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2432d06fc5fdSStefano Zampini       }
2433d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2434d06fc5fdSStefano Zampini       n_ISForEdges = 0;
2435d06fc5fdSStefano Zampini     }
2436d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
2437d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
2438d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2439d06fc5fdSStefano Zampini       }
2440d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2441d06fc5fdSStefano Zampini       n_ISForFaces = 0;
2442d06fc5fdSStefano Zampini     }
244370022509SStefano Zampini 
244470022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
244570022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
244670022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
244770022509SStefano Zampini     if (pcbddc->NullSpace) {
244870022509SStefano Zampini       PetscBool tbool[2],gbool[2];
244970022509SStefano Zampini 
245070022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2451b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
2452d06fc5fdSStefano Zampini         if (!ISForEdges) {
2453d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
2454d06fc5fdSStefano Zampini         }
2455b8ffe317SStefano Zampini       }
2456d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
2457d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
2458d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2459d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
2460d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
246198a51de6SStefano Zampini     }
246270022509SStefano Zampini #endif
246308122e43SStefano Zampini 
2464674ae819SStefano Zampini     /* check if near null space is attached to global mat */
2465674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2466674ae819SStefano Zampini     if (nearnullsp) {
2467674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2468f4ddd8eeSStefano Zampini       /* remove any stored info */
2469f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2470f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2471f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
2472f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2473f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
2474473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2475f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
2476f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2477f4ddd8eeSStefano Zampini       }
2478984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
2479984c4197SStefano Zampini       nnsp_size = 0;
2480674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
2481674ae819SStefano Zampini     }
2482984c4197SStefano Zampini     /* get max number of constraints on a single cc */
2483984c4197SStefano Zampini     max_constraints = nnsp_size;
2484984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
2485984c4197SStefano Zampini 
2486674ae819SStefano Zampini     /*
2487674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
24889162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
24899162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
24909162d606SStefano Zampini          There can be multiple constraints per connected component
2491674ae819SStefano Zampini                                                                                                                                                            */
2492674ae819SStefano Zampini     n_vertices = 0;
2493674ae819SStefano Zampini     if (ISForVertices) {
2494674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2495674ae819SStefano Zampini     }
24969162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
24979162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
24989162d606SStefano Zampini 
24999162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
25009162d606SStefano Zampini     total_counts *= max_constraints;
2501674ae819SStefano Zampini     total_counts += n_vertices;
25024641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
25039162d606SStefano Zampini 
2504674ae819SStefano Zampini     total_counts = 0;
2505674ae819SStefano Zampini     max_size_of_constraint = 0;
2506674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
25079162d606SStefano Zampini       IS used_is;
2508674ae819SStefano Zampini       if (i<n_ISForEdges) {
25099162d606SStefano Zampini         used_is = ISForEdges[i];
2510674ae819SStefano Zampini       } else {
25119162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
2512674ae819SStefano Zampini       }
25139162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2514674ae819SStefano Zampini       total_counts += j;
2515674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2516674ae819SStefano Zampini     }
25179162d606SStefano 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);
25189162d606SStefano Zampini 
2519984c4197SStefano Zampini     /* get local part of global near null space vectors */
2520785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2521984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2522984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2523e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2524e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2525984c4197SStefano Zampini     }
2526674ae819SStefano Zampini 
2527242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
2528242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
2529a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2530242a89d7SStefano Zampini 
2531984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2532a773dcb8SStefano Zampini     if (!skip_lapack) {
2533674ae819SStefano Zampini       PetscScalar temp_work;
2534911cabfeSStefano Zampini 
2535674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2536984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2537785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2538785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2539785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2540674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2541785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2542674ae819SStefano Zampini #endif
2543674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2544c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2545c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2546674ae819SStefano Zampini       lwork = -1;
2547674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2548674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2549c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2550674ae819SStefano Zampini #else
2551c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2552674ae819SStefano Zampini #endif
2553674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2554984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2555674ae819SStefano Zampini #else /* on missing GESVD */
2556674ae819SStefano Zampini       /* SVD */
2557674ae819SStefano Zampini       PetscInt max_n,min_n;
2558674ae819SStefano Zampini       max_n = max_size_of_constraint;
2559984c4197SStefano Zampini       min_n = max_constraints;
2560984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
2561674ae819SStefano Zampini         min_n = max_size_of_constraint;
2562984c4197SStefano Zampini         max_n = max_constraints;
2563674ae819SStefano Zampini       }
2564785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2565674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2566785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2567674ae819SStefano Zampini #endif
2568674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2569674ae819SStefano Zampini       lwork = -1;
2570e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2571e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2572b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2573674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2574674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
25759162d606SStefano 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));
2576674ae819SStefano Zampini #else
25779162d606SStefano 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));
2578674ae819SStefano Zampini #endif
2579674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2580984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2581984c4197SStefano Zampini #endif /* on missing GESVD */
2582674ae819SStefano Zampini       /* Allocate optimal workspace */
2583674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2584854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2585674ae819SStefano Zampini     }
2586674ae819SStefano Zampini     /* Now we can loop on constraining sets */
2587674ae819SStefano Zampini     total_counts = 0;
25889162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
25899162d606SStefano Zampini     constraints_data_ptr[0] = 0;
2590674ae819SStefano Zampini     /* vertices */
25919162d606SStefano Zampini     if (n_vertices) {
2592674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
25939162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2594674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
25959162d606SStefano Zampini         constraints_n[total_counts] = 1;
25969162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
25979162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
25989162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2599674ae819SStefano Zampini         total_counts++;
2600674ae819SStefano Zampini       }
2601674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2602674ae819SStefano Zampini       n_vertices = total_counts;
2603674ae819SStefano Zampini     }
2604984c4197SStefano Zampini 
2605674ae819SStefano Zampini     /* edges and faces */
26069162d606SStefano Zampini     total_counts_cc = total_counts;
2607911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
26089162d606SStefano Zampini       IS        used_is;
26099162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
26109162d606SStefano Zampini 
2611911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
26129162d606SStefano Zampini         used_is = ISForEdges[ncc];
2613984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2614674ae819SStefano Zampini       } else {
26159162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
2616984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2617674ae819SStefano Zampini       }
2618674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
26199162d606SStefano Zampini 
26209162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
26219162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2622984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
2623984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2624674ae819SStefano Zampini       if (nnsp_has_cnst) {
26255b08dc53SStefano Zampini         PetscScalar quad_value;
26269162d606SStefano Zampini 
26279162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
26289162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
26299162d606SStefano Zampini 
2630a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
2631674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2632a773dcb8SStefano Zampini         } else {
2633a773dcb8SStefano Zampini           quad_value = 1.0;
2634a773dcb8SStefano Zampini         }
2635674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
26369162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
2637674ae819SStefano Zampini         }
26389162d606SStefano Zampini         temp_constraints++;
2639674ae819SStefano Zampini         total_counts++;
2640674ae819SStefano Zampini       }
2641674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
2642984c4197SStefano Zampini         PetscReal real_value;
26439162d606SStefano Zampini         PetscScalar *ptr_to_data;
26449162d606SStefano Zampini 
2645984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
26469162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
2647674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
26489162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
2649674ae819SStefano Zampini         }
2650984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2651984c4197SStefano Zampini         /* check if array is null on the connected component */
2652e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
26539162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
26545b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2655674ae819SStefano Zampini           temp_constraints++;
2656674ae819SStefano Zampini           total_counts++;
26579162d606SStefano Zampini           if (!idxs_copied) {
26589162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
26599162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
2660674ae819SStefano Zampini           }
2661674ae819SStefano Zampini         }
26629162d606SStefano Zampini       }
26639162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
266445a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2665eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2666a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
26679162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
26689162d606SStefano Zampini 
26699162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2670a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
26719162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
2672a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
26739162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
2674a773dcb8SStefano Zampini         } else { /* perform SVD */
2675984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
26769162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2677674ae819SStefano Zampini 
2678674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2679984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
2680984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
2681984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
2682984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
2683984c4197SStefano Zampini                 from that computed using LAPACKgesvd
2684984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
2685984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
2686984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
2687674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
2688e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2689984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2690674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
2691674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
26929162d606SStefano 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));
2693674ae819SStefano Zampini             }
2694674ae819SStefano Zampini           }
2695e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
2696e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2697e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
2698674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2699c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
2700674ae819SStefano Zampini #else
2701c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
2702674ae819SStefano Zampini #endif
2703674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2704984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
2705984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
2706674ae819SStefano Zampini           j = 0;
2707984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
2708674ae819SStefano Zampini           total_counts = total_counts-j;
270945a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
2710e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
2711c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2712c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2713c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
2714c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2715c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
2716c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2717674ae819SStefano Zampini           if (j<temp_constraints) {
2718984c4197SStefano Zampini             PetscInt ii;
2719984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
2720674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27219162d606SStefano 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));
2722674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2723984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
2724674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
27259162d606SStefano 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];
2726674ae819SStefano Zampini               }
2727674ae819SStefano Zampini             }
2728674ae819SStefano Zampini           }
2729674ae819SStefano Zampini #else  /* on missing GESVD */
2730e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2731e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2732b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2733674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2734674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
27359162d606SStefano 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));
2736674ae819SStefano Zampini #else
27379162d606SStefano 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));
2738674ae819SStefano Zampini #endif
2739984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
2740674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2741984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
2742e310c8b4SStefano Zampini           k = temp_constraints;
2743e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
2744674ae819SStefano Zampini           j = 0;
2745e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
274645a1bb75SStefano Zampini           valid_constraints = k-j;
2747911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
2748984c4197SStefano Zampini #endif /* on missing GESVD */
2749674ae819SStefano Zampini         }
2750a773dcb8SStefano Zampini       }
27519162d606SStefano Zampini       /* update pointers information */
27529162d606SStefano Zampini       if (valid_constraints) {
27539162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
27549162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
27559162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
27569162d606SStefano Zampini         /* set change_of_basis flag */
275745a1bb75SStefano Zampini         if (boolforchange) {
2758b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
27599162d606SStefano Zampini         }
2760b3d85658SStefano Zampini         total_counts_cc++;
276145a1bb75SStefano Zampini       }
276245a1bb75SStefano Zampini     }
2763984c4197SStefano Zampini     /* free workspace */
27648f1c130eSStefano Zampini     if (!skip_lapack) {
2765984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
2766984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2767984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
2768984c4197SStefano Zampini #endif
2769984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
2770984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2771984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
2772984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2773984c4197SStefano Zampini #endif
2774984c4197SStefano Zampini     }
2775984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2776984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
2777984c4197SStefano Zampini     }
2778984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
2779cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
2780cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
2781cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2782cf5a6209SStefano Zampini     }
2783cf5a6209SStefano Zampini     if (n_ISForFaces) {
2784cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2785cf5a6209SStefano Zampini     }
2786cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
2787cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2788cf5a6209SStefano Zampini     }
2789cf5a6209SStefano Zampini     if (n_ISForEdges) {
2790cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2791cf5a6209SStefano Zampini     }
2792cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
279308122e43SStefano Zampini   } else {
279408122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2795984c4197SStefano Zampini 
279608122e43SStefano Zampini     total_counts = 0;
279708122e43SStefano Zampini     n_vertices = 0;
2798d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
2799d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
280008122e43SStefano Zampini     }
280108122e43SStefano Zampini     max_constraints = 0;
28029162d606SStefano Zampini     total_counts_cc = 0;
280308122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
280408122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
28059162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
280608122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
280708122e43SStefano Zampini     }
28089162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
28099162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
28109162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
28119162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
281274d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
28139162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
28149162d606SStefano Zampini     total_counts_cc = 0;
28159162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
28169162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
28179162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
281808122e43SStefano Zampini       }
281908122e43SStefano Zampini     }
28209162d606SStefano Zampini #if 0
28219162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
28229162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
28239162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
28249162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
28259162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
28269162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
28279162d606SStefano Zampini       }
28289162d606SStefano Zampini       printf("\n");
28299162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
28309162d606SStefano Zampini     }
28311b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
28328bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
28331b968477SStefano Zampini     }
28341b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
28358bec7fa6SStefano 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]);
28361b968477SStefano Zampini     }
283708122e43SStefano Zampini #endif
283808122e43SStefano Zampini 
28398bec7fa6SStefano Zampini     max_size_of_constraint = 0;
28409162d606SStefano 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]);
28419162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
284208122e43SStefano Zampini     /* Change of basis */
2843b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
284408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
284508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
284608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
2847b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
284808122e43SStefano Zampini         }
284908122e43SStefano Zampini       }
285008122e43SStefano Zampini     }
285108122e43SStefano Zampini   }
2852984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
2853019a44ceSStefano Zampini   /* allocating one extra space (in case an extra primal dof should be stored for the benign trick */
2854019a44ceSStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+1,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
285508122e43SStefano Zampini 
28569162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
28579162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
28589162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
28599162d606SStefano 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);
286008122e43SStefano Zampini   }
2861674ae819SStefano Zampini 
2862674ae819SStefano Zampini   /* Create constraint matrix */
2863674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
286416f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
2865984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
2866984c4197SStefano Zampini 
2867984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
2868a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
2869a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
287074d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
2871984c4197SStefano Zampini   total_primal_vertices=0;
2872b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
28739162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
28749162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2875984c4197SStefano Zampini     if (size_of_constraint == 1) {
28769162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
2877b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
287864efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
28799162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
28809162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
2881a717540cSStefano Zampini       }
2882b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
288374d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
2884a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
2885a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
2886a717540cSStefano Zampini       }
2887fa434743SStefano Zampini     } else {
2888b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
2889fa434743SStefano Zampini     }
2890a717540cSStefano Zampini   }
2891b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
2892b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
2893674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
289470022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2895b3d85658SStefano Zampini 
2896019a44ceSStefano Zampini   /* allocating one extra space (in case an extra primal dof should be stored for the benign trick */
2897019a44ceSStefano 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);
28980e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
28990e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
2900984c4197SStefano Zampini 
2901984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
290274d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
2903785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2904984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
290574d5cdf7SStefano Zampini 
2906984c4197SStefano Zampini   j = total_primal_vertices;
290774d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
2908b3d85658SStefano Zampini   cum = total_primal_vertices;
29099162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
29104641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2911b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
2912b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
2913b3d85658SStefano Zampini       cum++;
29149162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
291574d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
291674d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
291774d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
291874d5cdf7SStefano Zampini       }
29199162d606SStefano Zampini       j += constraints_n[i];
2920674ae819SStefano Zampini     }
2921674ae819SStefano Zampini   }
2922674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2923674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2924088faed8SStefano Zampini 
2925674ae819SStefano Zampini   /* set values in constraint matrix */
2926984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
29270e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2928674ae819SStefano Zampini   }
2929984c4197SStefano Zampini   total_counts = total_primal_vertices;
29309162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
29314641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
29329162d606SStefano Zampini       PetscInt *cols;
29339162d606SStefano Zampini 
29349162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
29359162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
29369162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
29379162d606SStefano Zampini         PetscInt    row = total_counts+k;
29389162d606SStefano Zampini         PetscScalar *vals;
29399162d606SStefano Zampini 
29409162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
29419162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
29429162d606SStefano Zampini       }
29439162d606SStefano Zampini       total_counts += constraints_n[i];
2944674ae819SStefano Zampini     }
2945674ae819SStefano Zampini   }
2946674ae819SStefano Zampini   /* assembling */
2947674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2948674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2949088faed8SStefano Zampini 
2950984c4197SStefano Zampini   /*
295145a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2952984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2953984c4197SStefano Zampini   */
2954674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2955674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2956026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2957984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2958984c4197SStefano Zampini     /* working stuff for GEQRF */
295981d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2960984c4197SStefano Zampini     PetscBLASInt lqr_work;
2961984c4197SStefano Zampini     /* working stuff for UNGQR */
2962984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2963984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2964984c4197SStefano Zampini     /* working stuff for TRTRS */
2965984c4197SStefano Zampini     PetscScalar  *trs_rhs;
29663f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2967984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2968984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2969984c4197SStefano Zampini     PetscScalar  *start_vals;
2970984c4197SStefano Zampini     /* working stuff for values insertion */
29714641a718SStefano Zampini     PetscBT      is_primal;
297264efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
2973906d46d4SStefano Zampini     /* matrix sizes */
2974906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2975906d46d4SStefano Zampini     /* temporary change of basis */
2976906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2977cf5a6209SStefano Zampini     /* extra space for debugging */
2978cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
2979984c4197SStefano Zampini 
2980906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2981906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
298216f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2983bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
2984906d46d4SStefano Zampini     /* nonzeros for local mat */
2985bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
2986bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
29879162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
2988a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
29899162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2990a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
29919162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
2992a717540cSStefano Zampini         } else {
29939162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
29949162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
2995a717540cSStefano Zampini         }
2996a717540cSStefano Zampini       }
2997a717540cSStefano Zampini     }
2998906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2999bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3000a717540cSStefano Zampini     /* Set initial identity in the matrix */
3001bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
3002906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3003a717540cSStefano Zampini     }
3004a717540cSStefano Zampini 
3005a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
3006a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3007a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3008a717540cSStefano Zampini     }
3009a717540cSStefano Zampini 
3010a717540cSStefano Zampini 
3011a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
3012a717540cSStefano Zampini     /*
3013a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3014a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3015a717540cSStefano Zampini 
3016a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
3017a717540cSStefano Zampini 
3018a6b551f4SStefano 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)
3019a6b551f4SStefano Zampini 
3020a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
3021a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
3022a717540cSStefano Zampini             |              ...                        |
3023a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
3024a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3025a717540cSStefano Zampini 
3026a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
3027a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3028a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3029a6b551f4SStefano Zampini 
3030a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
3031a717540cSStefano Zampini     */
3032a717540cSStefano Zampini     if (qr_needed) {
3033984c4197SStefano Zampini       /* space to store Q */
3034854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3035984c4197SStefano Zampini       /* first we issue queries for optimal work */
30363f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
30373f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
30383f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3039984c4197SStefano Zampini       lqr_work = -1;
30403f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3041984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3042984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3043785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3044984c4197SStefano Zampini       lgqr_work = -1;
30453f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
30463f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
30473f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
30483f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
30493f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
30503f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3051984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3052984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3053785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3054984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3055785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3056984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3057785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3058a717540cSStefano Zampini       /* allocating workspace for check */
3059a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3060cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3061a717540cSStefano Zampini       }
3062a717540cSStefano Zampini     }
3063984c4197SStefano Zampini     /* array to store whether a node is primal or not */
30644641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3065473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
30660e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
306739e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
306839e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
30694641a718SStefano Zampini     }
307039e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
307139e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
307239e2fb2aSStefano Zampini     }
307339e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3074984c4197SStefano Zampini 
3075a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
30769162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
30779162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
30784641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3079984c4197SStefano Zampini         /* get constraint info */
30809162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3081984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3082984c4197SStefano Zampini 
3083984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
30849162d606SStefano 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);
3085674ae819SStefano Zampini         }
3086984c4197SStefano Zampini 
3087fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3088a717540cSStefano Zampini 
3089a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3090a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
30919162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3092a717540cSStefano Zampini           }
3093984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
30949162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3095984c4197SStefano Zampini 
3096984c4197SStefano Zampini           /* compute QR decomposition of constraints */
30973f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
30983f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
30993f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3100674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31013f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3102984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3103674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3104984c4197SStefano Zampini 
3105984c4197SStefano Zampini           /* explictly compute R^-T */
3106984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3107984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
31083f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
31093f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
31103f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
31113f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3112984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31133f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3114984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3115984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3116984c4197SStefano Zampini 
3117a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
31183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
31193f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
31203f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
31213f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3122984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31233f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3124984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3125984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3126984c4197SStefano Zampini 
3127984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3128984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3129984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
31303f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
31313f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
31323f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
31333f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
31343f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
31353f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3136984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31379162d606SStefano 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));
3138984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
31399162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3140984c4197SStefano Zampini 
3141984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
31429162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3143984c4197SStefano Zampini           /* insert cols for primal dofs */
3144984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3145984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
31469162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3147906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3148984c4197SStefano Zampini           }
3149984c4197SStefano Zampini           /* insert cols for dual dofs */
3150984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
31519162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3152984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
31539162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3154906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3155984c4197SStefano Zampini               j++;
3156674ae819SStefano Zampini             }
3157674ae819SStefano Zampini           }
3158984c4197SStefano Zampini 
3159984c4197SStefano Zampini           /* check change of basis */
3160984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3161984c4197SStefano Zampini             PetscInt   ii,jj;
3162984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3163c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3164c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3165c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3166c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3167c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3168c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3169984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3170cf5a6209SStefano 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));
3171984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3172984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3173984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3174cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3175cf5a6209SStefano 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;
3176674ae819SStefano Zampini               }
3177674ae819SStefano Zampini             }
3178984c4197SStefano Zampini             if (!valid_qr) {
317922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3180984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3181984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3182cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3183cf5a6209SStefano 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]));
3184674ae819SStefano Zampini                   }
3185cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3186cf5a6209SStefano 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]));
3187984c4197SStefano Zampini                   }
3188984c4197SStefano Zampini                 }
3189984c4197SStefano Zampini               }
3190674ae819SStefano Zampini             } else {
319122d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3192674ae819SStefano Zampini             }
3193674ae819SStefano Zampini           }
3194a717540cSStefano Zampini         } else { /* simple transformation block */
3195a717540cSStefano Zampini           PetscInt    row,col;
3196a6b551f4SStefano Zampini           PetscScalar val,norm;
3197a6b551f4SStefano Zampini 
3198a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
31999162d606SStefano 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));
3200a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
32019162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
32029162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3203bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
32049162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3205906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
32069162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3207a717540cSStefano Zampini             } else {
3208a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
32099162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3210a717540cSStefano Zampini                 if (row != col) {
32119162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3212a717540cSStefano Zampini                 } else {
32139162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3214a717540cSStefano Zampini                 }
3215906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3216a717540cSStefano Zampini               }
3217a717540cSStefano Zampini             }
3218a717540cSStefano Zampini           }
321998a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
322022d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3221a717540cSStefano Zampini           }
3222674ae819SStefano Zampini         }
3223984c4197SStefano Zampini       } else {
3224984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
32259162d606SStefano 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);
3226674ae819SStefano Zampini         }
3227674ae819SStefano Zampini       }
3228674ae819SStefano Zampini     }
3229a717540cSStefano Zampini 
3230a717540cSStefano Zampini     /* free workspace */
3231a717540cSStefano Zampini     if (qr_needed) {
3232984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
3233cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3234984c4197SStefano Zampini       }
3235984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3236984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3237984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3238984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3239984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3240674ae819SStefano Zampini     }
3241a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3242906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3243906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3244906d46d4SStefano Zampini 
3245906d46d4SStefano Zampini     /* assembling of global change of variable */
3246bbb9e6c6SStefano Zampini     {
3247bbb9e6c6SStefano Zampini       Mat      tmat;
324816f15bc4SStefano Zampini       PetscInt bs;
324916f15bc4SStefano Zampini 
3250906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3251906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3252bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3253bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3254bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3255bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
325616f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
325716f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3258906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3259bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3260bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3261bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3262bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3263bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3264e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3265e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3266bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3267bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3268906d46d4SStefano Zampini     }
3269906d46d4SStefano Zampini     /* check */
3270906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
3271906d46d4SStefano Zampini       PetscReal error;
3272906d46d4SStefano Zampini       Vec       x,x_change;
3273906d46d4SStefano Zampini 
3274906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3275906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3276906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3277906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3278e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3279e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3280bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
3281e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3282e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3283906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
3284906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3285906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3286906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3287bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
3288906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
3289906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3290906d46d4SStefano Zampini     }
3291b96c3477SStefano Zampini 
3292b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
3293b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
3294b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
3295b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
3296ac632422SStefano Zampini         Mat                    S_new,tmat;
3297b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
3298b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
3299b087196eSStefano Zampini         const PetscScalar      *array;
3300b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
3301b087196eSStefano Zampini         PetscInt               i,n_V;
3302bbb9e6c6SStefano Zampini 
3303bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
33046816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
3305b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
3306b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
3307b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
3308b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
3309bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
3310b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
3311ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3312b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
3313ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3314b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3315b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
3316b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3317b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3318b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
3319b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
3320b087196eSStefano Zampini           PetscScalar val;
3321b087196eSStefano Zampini           PetscInt    idx;
3322b087196eSStefano Zampini 
3323b087196eSStefano Zampini           idx = idxs_V[i];
3324b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
3325b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
3326b087196eSStefano Zampini         }
3327b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3328b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3329ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
3330ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3331ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
3332ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3333b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
3334ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3335b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3336ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
3337ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3338ac632422SStefano Zampini         }
3339b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
3340b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3341b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3342b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3343b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
3344b96c3477SStefano Zampini       }
3345b96c3477SStefano Zampini     }
3346906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
3347906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
3348b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3349b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
3350b9b85e73SStefano Zampini   }
3351906d46d4SStefano Zampini 
3352906d46d4SStefano Zampini   /* set up change of basis context */
3353906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
3354906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
3355906d46d4SStefano Zampini 
3356906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
3357906d46d4SStefano Zampini       PetscInt global_size,local_size;
3358906d46d4SStefano Zampini 
3359906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3360906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3361906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
3362906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3363906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
3364906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
3365906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3366906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3367906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3368906d46d4SStefano Zampini     } else {
3369906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3370906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3371906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3372906d46d4SStefano Zampini     }
3373906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
3374906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3375906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3376906d46d4SStefano Zampini     } else {
3377906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3378906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3379906d46d4SStefano Zampini     }
3380906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3381906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3382906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3383906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3384b9b85e73SStefano Zampini   }
3385a717540cSStefano Zampini 
3386019a44ceSStefano Zampini   /* add pressure dof to set of primal nodes for numbering purposes */
3387c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
3388c9ed8603SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx;
3389d16cbb6bSStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx;
3390019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
3391019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
3392019a44ceSStefano Zampini     pcbddc->local_primal_size++;
3393019a44ceSStefano Zampini   }
3394019a44ceSStefano Zampini 
3395019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
3396727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
3397727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
3398aff50787SStefano 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);
3399c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
34000e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
3401aff50787SStefano 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);
3402727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3403727cdba6SStefano Zampini     }
34040e6343abSStefano Zampini   }
34050e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3406727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3407727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3408727cdba6SStefano Zampini 
3409a717540cSStefano Zampini   /* flush dbg viewer */
3410b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
3411b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3412b8ffe317SStefano Zampini   }
3413a717540cSStefano Zampini 
3414e310c8b4SStefano Zampini   /* free workspace */
3415a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
34164641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
341708122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
34189162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
34199162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
342008122e43SStefano Zampini   } else {
34219162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
34229162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
34239162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
342408122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
342508122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
34269162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
34279162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
342808122e43SStefano Zampini   }
3429674ae819SStefano Zampini   PetscFunctionReturn(0);
3430674ae819SStefano Zampini }
3431674ae819SStefano Zampini 
3432674ae819SStefano Zampini #undef __FUNCT__
3433674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
3434674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3435674ae819SStefano Zampini {
3436674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3437674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
3438674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
34397fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
3440674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
3441674ae819SStefano Zampini 
3442674ae819SStefano Zampini   PetscFunctionBegin;
34438e61c736SStefano Zampini   /* Reset previously computed graph */
34448e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3445674ae819SStefano Zampini   /* Init local Graph struct */
34467fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
34473bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3448674ae819SStefano Zampini 
3449575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
34505099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
34515099eff2SStefano 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);
3452575ad6abSStefano Zampini   }
34539577ea80SStefano Zampini 
3454674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
34554d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
34564d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
34574d379d7bSStefano Zampini     PetscInt  nvtxs;
3458e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
3459674ae819SStefano Zampini 
34604d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
34612fffb893SStefano Zampini 
34622fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
34632fffb893SStefano Zampini       if (flg_row) {
34644d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3465b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
34662fffb893SStefano Zampini       }
34672fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
34689b28b941SStefano 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 */
34694d379d7bSStefano Zampini       IS                     is_dummy;
34704d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
34714d379d7bSStefano Zampini       PetscInt               j,sum;
34724d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
34734d379d7bSStefano Zampini       const PetscInt         *idxs;
34744d379d7bSStefano Zampini       PCBDDCGraph            graph;
34754d379d7bSStefano Zampini       PetscBT                is_on_boundary;
34764d379d7bSStefano Zampini 
34774d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
34784d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
34794d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
34804d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
34817fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
34824d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3483e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3484e496cd5dSStefano Zampini       if (flg_row) {
34854d379d7bSStefano Zampini         graph->xadj = xadj;
34864d379d7bSStefano Zampini         graph->adjncy = adjncy;
3487e496cd5dSStefano Zampini       }
34884d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
34894d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3490e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
34914d379d7bSStefano Zampini 
34924d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
34939b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
34944d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
34954d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
34964d379d7bSStefano Zampini         }
34974d379d7bSStefano Zampini       }
34984d379d7bSStefano Zampini 
3499e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
35004d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
35014d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
35024d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
35034d379d7bSStefano Zampini       }
35044d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
35054d379d7bSStefano Zampini 
3506e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
35074d379d7bSStefano Zampini       sum = 0;
35084d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
35094d379d7bSStefano Zampini         PetscInt sizecc = 0;
35104d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
35114d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
35124d379d7bSStefano Zampini             sizecc++;
35134d379d7bSStefano Zampini           }
35144d379d7bSStefano Zampini         }
35154d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
35164d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
35174d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
35184d379d7bSStefano Zampini           }
35194d379d7bSStefano Zampini         }
35204d379d7bSStefano Zampini         sum += sizecc*sizecc;
35214d379d7bSStefano Zampini       }
35224d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
35234d379d7bSStefano Zampini       sum = 0;
3524e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
35254d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
35264d379d7bSStefano Zampini         cxadj[i] = sum;
35274d379d7bSStefano Zampini         sum += temp;
35284d379d7bSStefano Zampini       }
3529e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
35304d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
35314d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
35324d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
35334d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
35344d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
35354d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
35364d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
35374d379d7bSStefano Zampini                 sizecc++;
35384d379d7bSStefano Zampini               }
35394d379d7bSStefano Zampini             }
35404d379d7bSStefano Zampini           }
35414d379d7bSStefano Zampini         }
35424d379d7bSStefano Zampini       }
35439b28b941SStefano Zampini       if (sum) {
3544e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
35454d379d7bSStefano Zampini       } else {
35464d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
35474d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
35484d379d7bSStefano Zampini       }
35494d379d7bSStefano Zampini       graph->xadj = 0;
35504d379d7bSStefano Zampini       graph->adjncy = 0;
35514d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
35524d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
35534d379d7bSStefano Zampini     }
3554674ae819SStefano Zampini   }
35559b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
35569b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3557674ae819SStefano Zampini   }
3558674ae819SStefano Zampini 
355963602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3560674ae819SStefano Zampini   vertex_size = 1;
356163602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
356263602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
356395ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
356463602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3565e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
356663602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3567674ae819SStefano Zampini       }
356863602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
356963602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
357063602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3571674ae819SStefano Zampini     }
357263602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3573674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
357463602bcaSStefano Zampini   } else {
357563602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
357663602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3577854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
357863602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
357963602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
358063602bcaSStefano Zampini       }
358163602bcaSStefano Zampini     }
3582674ae819SStefano Zampini   }
3583674ae819SStefano Zampini 
3584674ae819SStefano Zampini   /* Setup of Graph */
3585785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3586e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3587785d1243SStefano Zampini   }
3588785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3589e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3590785d1243SStefano Zampini   }
3591302440fdSBarry Smith   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);CHKERRQ(ierr);
3592674ae819SStefano Zampini 
3593674ae819SStefano Zampini   /* Graph's connected components analysis */
3594674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3595674ae819SStefano Zampini 
3596674ae819SStefano Zampini   /* print some info to stdout */
3597674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3598302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3599674ae819SStefano Zampini   }
3600fb180af4SStefano Zampini 
3601fb180af4SStefano Zampini   /* mark topography has done */
3602fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3603674ae819SStefano Zampini   PetscFunctionReturn(0);
3604674ae819SStefano Zampini }
3605674ae819SStefano Zampini 
3606dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3607674ae819SStefano Zampini #undef __FUNCT__
3608674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3609dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3610674ae819SStefano Zampini {
3611dc456d91SStefano Zampini   PetscSF        sf;
3612dc456d91SStefano Zampini   PetscLayout    map;
3613dc456d91SStefano Zampini   const PetscInt *idxs;
3614dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
3615dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
3616dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
3617dc456d91SStefano Zampini   PetscMPIInt    commsize;
3618674ae819SStefano Zampini   PetscBool      first_found;
3619674ae819SStefano Zampini   PetscErrorCode ierr;
3620674ae819SStefano Zampini 
3621674ae819SStefano Zampini   PetscFunctionBegin;
3622dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
3623dc456d91SStefano Zampini   if (subset_mult) {
3624dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
3625dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
3626dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
3627674ae819SStefano Zampini   }
3628dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
3629dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
3630dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
3631dc456d91SStefano Zampini   for (i=0;i<n;i++) {
3632dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
3633dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
3634674ae819SStefano Zampini   }
3635dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
3636dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3637dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
3638dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
3639dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
3640dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
3641dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
3642dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
3643dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
3644dc456d91SStefano Zampini 
3645dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
3646dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
3647dc456d91SStefano Zampini   if (subset_mult) {
3648dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3649dc456d91SStefano Zampini 
3650dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3651dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
3652dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3653674ae819SStefano Zampini   } else {
3654dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
3655674ae819SStefano Zampini   }
3656dc456d91SStefano Zampini   /* local size of new subset */
3657dc456d91SStefano Zampini   n_n = 0;
3658dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
3659dc456d91SStefano Zampini 
3660dc456d91SStefano Zampini   /* global indexes in layout */
3661dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
3662dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
3663dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
3664dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
3665dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
3666dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
3667dc456d91SStefano Zampini 
3668dc456d91SStefano Zampini   /* reduce from leaves to roots */
3669dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
367064a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
367164a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
3672dc456d91SStefano Zampini 
3673dc456d91SStefano Zampini   /* count indexes in local part of layout */
3674674ae819SStefano Zampini   nlocals = 0;
3675674ae819SStefano Zampini   first_index = -1;
3676674ae819SStefano Zampini   first_found = PETSC_FALSE;
3677dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
3678dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
3679674ae819SStefano Zampini       first_found = PETSC_TRUE;
3680674ae819SStefano Zampini       first_index = i;
3681674ae819SStefano Zampini     }
3682dc456d91SStefano Zampini     nlocals += root_data[i];
3683674ae819SStefano Zampini   }
3684dc456d91SStefano Zampini 
3685dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
36865fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
3687dc456d91SStefano Zampini   start = 0;
368864a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
36895fa240b1SStefano Zampini #else
369064a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
36915fa240b1SStefano Zampini   start = start-nlocals;
36925fa240b1SStefano Zampini #endif
36935fa240b1SStefano Zampini 
3694dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
3695dc456d91SStefano Zampini     *N_n = start + nlocals;
3696dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
3697dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3698674ae819SStefano Zampini   }
36995fa240b1SStefano Zampini 
37005fa240b1SStefano Zampini   /* adapt root data with cumulative */
3701674ae819SStefano Zampini   if (first_found) {
3702dc456d91SStefano Zampini     PetscInt old_index;
3703dc456d91SStefano Zampini 
3704dc456d91SStefano Zampini     root_data[first_index] += start;
3705674ae819SStefano Zampini     old_index = first_index;
3706dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
3707dc456d91SStefano Zampini       if (root_data[i]) {
3708dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
3709674ae819SStefano Zampini         old_index = i;
3710674ae819SStefano Zampini       }
3711674ae819SStefano Zampini     }
3712674ae819SStefano Zampini   }
3713dc456d91SStefano Zampini 
3714dc456d91SStefano Zampini   /* from roots to leaves */
3715dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3716dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3717dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
3718dc456d91SStefano Zampini 
3719dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
3720dc456d91SStefano Zampini   if (subset_mult) {
3721dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3722dc456d91SStefano Zampini     PetscInt        cum;
3723dc456d91SStefano Zampini 
3724dc456d91SStefano Zampini     cum = 0;
3725dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3726dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3727dc456d91SStefano Zampini       PetscInt j;
3728dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
3729674ae819SStefano Zampini     }
3730dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3731674ae819SStefano Zampini   } else {
3732dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3733dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
3734674ae819SStefano Zampini     }
3735674ae819SStefano Zampini   }
3736dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
3737dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
3738674ae819SStefano Zampini   PetscFunctionReturn(0);
3739674ae819SStefano Zampini }
37409a7d3425SStefano Zampini 
37419a7d3425SStefano Zampini #undef __FUNCT__
37429a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
37439a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
37449a7d3425SStefano Zampini {
37459a7d3425SStefano Zampini   PetscInt       i,j;
37469a7d3425SStefano Zampini   PetscScalar    *alphas;
37479a7d3425SStefano Zampini   PetscErrorCode ierr;
37489a7d3425SStefano Zampini 
37499a7d3425SStefano Zampini   PetscFunctionBegin;
37509a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
3751785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
37529a7d3425SStefano Zampini   for (i=0;i<n;i++) {
37539a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
37549a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
37559a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
37569a7d3425SStefano Zampini   }
37579a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
37589a7d3425SStefano Zampini   PetscFunctionReturn(0);
37599a7d3425SStefano Zampini }
37609a7d3425SStefano Zampini 
3761e7931f94SStefano Zampini #undef __FUNCT__
376270cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
3763b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
3764e7931f94SStefano Zampini {
376552e5ac9dSStefano Zampini   IS             ranks_send_to;
3766e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
3767e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
376852e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
376952e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
37703837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
37712b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
3772e7931f94SStefano Zampini   PetscSubcomm   subcomm;
377352e5ac9dSStefano Zampini   PetscErrorCode ierr;
3774a57a6d2fSStefano Zampini 
3775e7931f94SStefano Zampini   PetscFunctionBegin;
37762b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
37772b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
37782b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
3779e7931f94SStefano Zampini 
3780e7931f94SStefano Zampini   /* Get info on mapping */
37813bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
37823bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3783e7931f94SStefano Zampini 
3784e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
3785785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
3786e7931f94SStefano Zampini   xadj[0] = 0;
3787e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
3788785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
3789785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
3790e7931f94SStefano Zampini 
37912b510759SStefano Zampini   if (threshold) {
3792d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
37932b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3794d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3795d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3796d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3797d023bfaeSStefano Zampini         xadj_count++;
3798e7931f94SStefano Zampini       }
3799e7931f94SStefano Zampini     }
3800d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3801c8587f34SStefano Zampini   } else {
3802e7931f94SStefano Zampini     if (xadj[1]) {
3803e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3804e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3805c8587f34SStefano Zampini     }
3806e7931f94SStefano Zampini   }
38073bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3808e7931f94SStefano Zampini   if (use_square) {
3809e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3810e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3811e7931f94SStefano Zampini     }
3812e7931f94SStefano Zampini   }
3813e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3814e7931f94SStefano Zampini 
38153837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3816e7931f94SStefano Zampini 
3817e7931f94SStefano Zampini   /*
3818e7931f94SStefano Zampini     Restrict work on active processes only.
3819e7931f94SStefano Zampini   */
3820e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3821e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3822e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
38232b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3824d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3825e7931f94SStefano Zampini   if (color) {
3826e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3827e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3828e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3829c8587f34SStefano Zampini   } else {
383052e5ac9dSStefano Zampini     Mat             subdomain_adj;
383152e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
383252e5ac9dSStefano Zampini     MatPartitioning partitioner;
383352e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
383452e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
3835b0c7d250SStefano Zampini     PetscBool       aggregate;
3836b0c7d250SStefano Zampini 
3837306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
3838785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3839e7931f94SStefano Zampini     prank = rank;
3840306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
38418002ef2cSStefano Zampini     /*
3842e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3843e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3844c8587f34SStefano Zampini     }
38458002ef2cSStefano Zampini     */
3846e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3847e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3848c8587f34SStefano Zampini     }
3849e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3850b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
3851b0c7d250SStefano Zampini     if (aggregate) {
3852b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
3853b0c7d250SStefano Zampini       PetscMPIInt nrank;
3854b0c7d250SStefano Zampini       PetscScalar *vals;
3855b0c7d250SStefano Zampini 
3856b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
3857b0c7d250SStefano Zampini       lrows = 0;
3858b0c7d250SStefano Zampini       if (nrank<redprocs) {
3859b0c7d250SStefano Zampini         lrows = size/redprocs;
3860b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
3861b0c7d250SStefano Zampini       }
38625fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
3863b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
3864b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3865b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3866b0c7d250SStefano Zampini       row = nrank;
3867b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
3868b0c7d250SStefano Zampini       cols = adjncy;
3869b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
3870b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
3871b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
3872b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3873b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
387452e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
387552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
387652e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3877b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
3878b0c7d250SStefano Zampini     } else {
3879306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
3880b0c7d250SStefano Zampini     }
388122b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3882e7931f94SStefano Zampini 
3883e7931f94SStefano Zampini     /* Partition */
3884306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
3885e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3886e7931f94SStefano Zampini     if (use_vwgt) {
38873837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3888e7931f94SStefano Zampini       v_wgt[0] = local_size;
3889e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3890c8587f34SStefano Zampini     }
389128143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
389228143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3893e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3894e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
389522b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3896e7931f94SStefano Zampini 
389752e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
389852e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
389952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
390052e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3901b0c7d250SStefano Zampini     if (!redprocs) {
3902b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
390328143c3dSStefano Zampini     } else {
3904b0c7d250SStefano Zampini       PetscInt    idxs[1];
3905b0c7d250SStefano Zampini       PetscMPIInt tag;
3906b0c7d250SStefano Zampini       MPI_Request *reqs;
3907b0c7d250SStefano Zampini 
3908b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
3909b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
3910b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
3911b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
391228143c3dSStefano Zampini       }
3913b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
3914b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3915b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
3916b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
3917e7931f94SStefano Zampini     }
391852e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3919e7931f94SStefano Zampini     /* clean up */
3920e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
392152e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
3922e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3923e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3924e7931f94SStefano Zampini   }
3925e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3926e7931f94SStefano Zampini 
3927e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3928e7931f94SStefano Zampini   i = 1;
3929e7931f94SStefano Zampini   if (color) i=0;
3930e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3931e7931f94SStefano Zampini   /* get back IS */
3932e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3933e7931f94SStefano Zampini   PetscFunctionReturn(0);
3934e7931f94SStefano Zampini }
3935e7931f94SStefano Zampini 
3936e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3937e7931f94SStefano Zampini 
3938e7931f94SStefano Zampini #undef __FUNCT__
3939e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
394053a05cb3SStefano 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[])
3941e7931f94SStefano Zampini {
394270cf5478SStefano Zampini   Mat                    local_mat;
3943e7931f94SStefano Zampini   IS                     is_sends_internal;
39449d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
394528143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
39469d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3947e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3948e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3949e7931f94SStefano Zampini   const PetscInt*        is_indices;
3950e7931f94SStefano Zampini   MatType                new_local_type;
3951e7931f94SStefano Zampini   /* buffers */
3952e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
395328143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
39549d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3955e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3956e7931f94SStefano Zampini   /* MPI */
395728143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
395828143c3dSStefano Zampini   PetscSubcomm           subcomm;
3959e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
396028143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
396128143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
396228143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
396328143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
396428143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3965e7931f94SStefano Zampini   PetscErrorCode         ierr;
3966e7931f94SStefano Zampini 
3967e7931f94SStefano Zampini   PetscFunctionBegin;
396828143c3dSStefano Zampini   /* TODO: add missing checks */
396928143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
397028143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
397128143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
397228143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3973e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
397428143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3975e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3976e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3977e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3978e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3979e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
398028143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
398170cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
398270cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
398328143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
398470cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
398570cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
398670cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
398770cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
398870cf5478SStefano Zampini   }
3989e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3990e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3991e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3992e7931f94SStefano Zampini   if (!is_sends) {
399328143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
3994b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
3995c8587f34SStefano Zampini   } else {
3996e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3997e7931f94SStefano Zampini     is_sends_internal = is_sends;
3998c8587f34SStefano Zampini   }
3999e7931f94SStefano Zampini 
4000e7931f94SStefano Zampini   /* get comm */
4001a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4002e7931f94SStefano Zampini 
4003e7931f94SStefano Zampini   /* compute number of sends */
4004e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4005e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4006e7931f94SStefano Zampini 
4007e7931f94SStefano Zampini   /* compute number of receives */
4008e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4009785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4010e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4011e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4012e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4013e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4014e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
4015e7931f94SStefano Zampini 
401628143c3dSStefano Zampini   /* restrict comm if requested */
401728143c3dSStefano Zampini   subcomm = 0;
401828143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
401928143c3dSStefano Zampini   if (restrict_comm) {
4020779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
4021779c1cceSStefano Zampini 
402228143c3dSStefano Zampini     color = 0;
402353a05cb3SStefano Zampini     if (restrict_full) {
402453a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
402553a05cb3SStefano Zampini     } else {
402653a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
402753a05cb3SStefano Zampini     }
402828143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
402928143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
403028143c3dSStefano Zampini     /* check if reuse has been requested */
403128143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
403228143c3dSStefano Zampini       if (*mat_n) {
403328143c3dSStefano Zampini         PetscMPIInt subcommsize2;
403428143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
403528143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
403628143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
403728143c3dSStefano Zampini       } else {
403828143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
403928143c3dSStefano Zampini       }
404028143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
4041779c1cceSStefano Zampini       PetscMPIInt rank;
4042779c1cceSStefano Zampini 
4043779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
404428143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
404528143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
404628143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4047306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
404828143c3dSStefano Zampini     }
404928143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
405028143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
405128143c3dSStefano Zampini   } else {
405228143c3dSStefano Zampini     comm_n = comm;
405328143c3dSStefano Zampini   }
405428143c3dSStefano Zampini 
4055e7931f94SStefano Zampini   /* prepare send/receive buffers */
4056785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4057e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4058785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4059e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
406028143c3dSStefano Zampini   if (nis) {
4061854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
406228143c3dSStefano Zampini   }
4063e7931f94SStefano Zampini 
406428143c3dSStefano Zampini   /* Get data from local matrices */
4065e7931f94SStefano Zampini   if (!isdense) {
4066a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4067e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4068e7931f94SStefano Zampini     /*
4069e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4070e7931f94SStefano Zampini        send_buffer_idxs should contain:
4071e7931f94SStefano Zampini        - MatType_PRIVATE type
4072e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4073e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4074e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4075e7931f94SStefano Zampini     */
4076e7931f94SStefano Zampini   } else {
4077e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
40783bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4079854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4080e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4081e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
40823bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4083e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
40843bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4085e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4086e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4087e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4088e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4089c8587f34SStefano Zampini     }
4090c8587f34SStefano Zampini   }
4091e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
409228143c3dSStefano Zampini   /* additional is (if any) */
409328143c3dSStefano Zampini   if (nis) {
409428143c3dSStefano Zampini     PetscMPIInt psum;
409528143c3dSStefano Zampini     PetscInt j;
409628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
409728143c3dSStefano Zampini       PetscInt plen;
409828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
409928143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
410028143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
410128143c3dSStefano Zampini     }
4102854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
410328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
410428143c3dSStefano Zampini       PetscInt plen;
410528143c3dSStefano Zampini       const PetscInt *is_array_idxs;
410628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
410728143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
410828143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
410928143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
411028143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
411128143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
411228143c3dSStefano Zampini     }
411328143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
411428143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
411528143c3dSStefano Zampini     }
411628143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
411728143c3dSStefano Zampini   }
411828143c3dSStefano Zampini 
4119e7931f94SStefano Zampini   buf_size_idxs = 0;
4120e7931f94SStefano Zampini   buf_size_vals = 0;
412128143c3dSStefano Zampini   buf_size_idxs_is = 0;
4122e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4123e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4124e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
412528143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4126e7931f94SStefano Zampini   }
4127785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4128785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
412995ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4130e7931f94SStefano Zampini 
4131e7931f94SStefano Zampini   /* get new tags for clean communications */
4132e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4133e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
413428143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4135e7931f94SStefano Zampini 
4136e7931f94SStefano Zampini   /* allocate for requests */
4137785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4138785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
413995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4140785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4141785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
414295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4143e7931f94SStefano Zampini 
4144e7931f94SStefano Zampini   /* communications */
4145e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4146e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
414728143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4148e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4149e7931f94SStefano Zampini     source_dest = onodes[i];
4150e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4151e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4152e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4153e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
415428143c3dSStefano Zampini     if (nis) {
415528143c3dSStefano 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);
415628143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
415728143c3dSStefano Zampini     }
4158e7931f94SStefano Zampini   }
4159e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4160e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4161e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4162e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
416328143c3dSStefano Zampini     if (nis) {
416428143c3dSStefano 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);
416528143c3dSStefano Zampini     }
4166e7931f94SStefano Zampini   }
4167e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4168e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4169e7931f94SStefano Zampini 
4170e7931f94SStefano Zampini   /* assemble new l2g map */
4171e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4172e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
41739d30be91SStefano Zampini   new_local_rows = 0;
4174e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
41759d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4176e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4177e7931f94SStefano Zampini   }
41789d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4179e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
41809d30be91SStefano Zampini   new_local_rows = 0;
4181e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
41829d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
41839d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4184e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4185e7931f94SStefano Zampini   }
41869d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
41879d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4188e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4189e7931f94SStefano Zampini 
4190e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4191e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4192e7931f94SStefano 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) */
4193e7931f94SStefano Zampini   if (n_recvs) {
419428143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4195e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4196e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4197e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4198e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4199e7931f94SStefano Zampini         break;
4200e7931f94SStefano Zampini       }
4201e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4202e7931f94SStefano Zampini     }
4203e7931f94SStefano Zampini     switch (new_local_type_private) {
420428143c3dSStefano Zampini       case MATDENSE_PRIVATE:
420528143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4206e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4207e7931f94SStefano Zampini           bs = 1;
420828143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
420928143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
421028143c3dSStefano Zampini           bs = 1;
421128143c3dSStefano Zampini         }
4212e7931f94SStefano Zampini         break;
4213e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4214e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4215e7931f94SStefano Zampini         bs = 1;
4216e7931f94SStefano Zampini         break;
4217e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4218e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4219e7931f94SStefano Zampini         break;
4220e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4221e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4222e7931f94SStefano Zampini         break;
4223e7931f94SStefano Zampini       default:
42249d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4225e7931f94SStefano Zampini         break;
4226e7931f94SStefano Zampini     }
422728143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
422828143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
422928143c3dSStefano Zampini     bs = 1;
4230e7931f94SStefano Zampini   }
4231e7931f94SStefano Zampini 
423270cf5478SStefano Zampini   /* create MATIS object if needed */
423370cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4234e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4235e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
423670cf5478SStefano Zampini   } else {
423770cf5478SStefano Zampini     /* it also destroys the local matrices */
423870cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
423970cf5478SStefano Zampini   }
424070cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4241e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
42429d30be91SStefano Zampini 
42439d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
42449d30be91SStefano Zampini 
42459d30be91SStefano Zampini   /* Global to local map of received indices */
42469d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
42479d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
42489d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
42499d30be91SStefano Zampini 
42509d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
42519d30be91SStefano Zampini   buf_size_idxs = 0;
42529d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
42539d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
42549d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
42559d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
42569d30be91SStefano Zampini   }
42579d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
42589d30be91SStefano Zampini 
42599d30be91SStefano Zampini   /* set preallocation */
42609d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
42619d30be91SStefano Zampini   if (!newisdense) {
42629d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
42639d30be91SStefano Zampini 
42649d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
42659d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
42669d30be91SStefano Zampini     if (n_recvs) {
42679d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
42689d30be91SStefano Zampini     }
42699d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
42709d30be91SStefano Zampini       PetscInt j;
42719d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
42729d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
42739d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
42749d30be91SStefano Zampini         }
42759d30be91SStefano Zampini       } else {
42769d30be91SStefano Zampini         /* TODO */
42779d30be91SStefano Zampini       }
42789d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
42799d30be91SStefano Zampini     }
42809d30be91SStefano Zampini     if (new_local_nnz) {
42819d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
42829d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
42839d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
42849d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
42859d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
42869d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
42879d30be91SStefano Zampini     } else {
42889d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
42899d30be91SStefano Zampini     }
42909d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
42919d30be91SStefano Zampini   } else {
42929d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
42939d30be91SStefano Zampini   }
4294e7931f94SStefano Zampini 
4295e7931f94SStefano Zampini   /* set values */
4296e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
42979d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
4298e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4299e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
4300e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
43019d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
4302e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4303e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4304e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
430528143c3dSStefano Zampini     } else {
430628143c3dSStefano Zampini       /* TODO */
4307e7931f94SStefano Zampini     }
4308e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4309e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
4310e7931f94SStefano Zampini   }
4311e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4312e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
431370cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
431470cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
43159d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
43169d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
4317e7931f94SStefano Zampini 
4318dfd14d43SStefano Zampini #if 0
431928143c3dSStefano Zampini   if (!restrict_comm) { /* check */
4320e7931f94SStefano Zampini     Vec       lvec,rvec;
4321e7931f94SStefano Zampini     PetscReal infty_error;
4322e7931f94SStefano Zampini 
43232a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
4324e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
4325e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
4326e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
432770cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
4328e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4329e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
4330e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
4331e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
4332e7931f94SStefano Zampini   }
433328143c3dSStefano Zampini #endif
4334e7931f94SStefano Zampini 
433528143c3dSStefano Zampini   /* assemble new additional is (if any) */
433628143c3dSStefano Zampini   if (nis) {
433728143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
433828143c3dSStefano Zampini 
433928143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4340854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
434128143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
434228143c3dSStefano Zampini     psum = 0;
434328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
434428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
434528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
434628143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
434728143c3dSStefano Zampini         psum += plen;
434828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
434928143c3dSStefano Zampini       }
435028143c3dSStefano Zampini     }
4351854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
4352854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
435328143c3dSStefano Zampini     for (i=1;i<nis;i++) {
435428143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
435528143c3dSStefano Zampini     }
435628143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
435728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
435828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
435928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
436028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
436128143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
436228143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
436328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
436428143c3dSStefano Zampini       }
436528143c3dSStefano Zampini     }
436628143c3dSStefano Zampini     for (i=0;i<nis;i++) {
436728143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
436828143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
436928143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
437028143c3dSStefano Zampini     }
437128143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
437228143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
437328143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
437428143c3dSStefano Zampini   }
4375e7931f94SStefano Zampini   /* free workspace */
437628143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4377e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4378e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4379e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4380e7931f94SStefano Zampini   if (isdense) {
4381e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4382e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4383e7931f94SStefano Zampini   } else {
4384e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4385e7931f94SStefano Zampini   }
438628143c3dSStefano Zampini   if (nis) {
438728143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
438828143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
438928143c3dSStefano Zampini   }
4390e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4391e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
439228143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4393e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4394e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
439528143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4396e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4397e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4398e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4399e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4400e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
440128143c3dSStefano Zampini   if (nis) {
440228143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
440328143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
440428143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
440528143c3dSStefano Zampini   }
440628143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
440728143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
440828143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
440928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
441028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
441128143c3dSStefano Zampini     }
441253a05cb3SStefano Zampini     *mat_n = NULL;
441328143c3dSStefano Zampini   }
4414e7931f94SStefano Zampini   PetscFunctionReturn(0);
4415e7931f94SStefano Zampini }
4416a57a6d2fSStefano Zampini 
441712edc857SStefano Zampini /* temporary hack into ksp private data structure */
4418af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
441912edc857SStefano Zampini 
4420c8587f34SStefano Zampini #undef __FUNCT__
4421c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4422c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4423c8587f34SStefano Zampini {
4424c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4425c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
442620a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
44279881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
442820a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
44296e683305SStefano Zampini   IS                     coarse_is,*isarray;
44306e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
44316e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
4432f9eb5b7dSStefano Zampini   PC                     pc_temp;
4433c8587f34SStefano Zampini   PCType                 coarse_pc_type;
4434c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
4435f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
44364f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
44376e683305SStefano Zampini   Mat                    t_coarse_mat_is;
44386e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
44396e683305SStefano Zampini   PetscMPIInt            all_procs;
444074e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
444168457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
444222bc73bbSStefano Zampini   PetscScalar            *array;
44439881197aSStefano Zampini   PetscErrorCode         ierr;
4444fdc09c96SStefano Zampini 
4445c8587f34SStefano Zampini   PetscFunctionBegin;
4446c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
444768457ee5SStefano 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 */
4448fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
44495a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
4450fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
4451f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4452f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4453f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
4454fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
445551bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
445651bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4457dc4bcba2SStefano Zampini         PC        pc;
4458dc4bcba2SStefano Zampini         PetscBool isbddc;
4459dc4bcba2SStefano Zampini 
4460dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
4461dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4462dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4463dc4bcba2SStefano Zampini         if (isbddc) {
4464dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4465dc4bcba2SStefano Zampini         }
4466727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4467fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
4468fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
4469fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
4470f4ddd8eeSStefano Zampini       }
4471fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4472fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
4473f4ddd8eeSStefano Zampini     }
447470cf5478SStefano Zampini     /* reset any subassembling information */
447570cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
44766e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
44776e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4478fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
4479f4ddd8eeSStefano Zampini   }
4480c8587f34SStefano Zampini 
44816e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
44822b510759SStefano Zampini   im_active = !!(pcis->n);
44832b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
44846e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
44856e683305SStefano Zampini   void_procs = all_procs-active_procs;
44866e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
448774e2c79eSStefano Zampini   redist = PETSC_FALSE;
448822bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
44896e683305SStefano Zampini     csin_ml = PETSC_TRUE;
44906e683305SStefano Zampini     ncoarse_ml = void_procs;
4491779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4492779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
44936e683305SStefano Zampini       csin_ds = PETSC_TRUE;
449418a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
449518a45a71SStefano Zampini       redist = PETSC_TRUE;
449618a45a71SStefano Zampini     } else {
44976e683305SStefano Zampini       csin_ds = PETSC_TRUE;
4498779c1cceSStefano Zampini       ncoarse_ds = active_procs;
4499779c1cceSStefano Zampini       redist = PETSC_TRUE;
450018a45a71SStefano Zampini     }
45016e683305SStefano Zampini   } else {
45026e683305SStefano Zampini     csin_ml = PETSC_FALSE;
45036e683305SStefano Zampini     ncoarse_ml = all_procs;
45046e683305SStefano Zampini     if (void_procs) {
45056e683305SStefano Zampini       csin_ds = PETSC_TRUE;
45066e683305SStefano Zampini       ncoarse_ds = void_procs;
45076e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
45086e683305SStefano Zampini     } else {
4509779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
451074e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
451174e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
451274e2c79eSStefano Zampini         redist = PETSC_TRUE;
451374e2c79eSStefano Zampini       } else {
45146e683305SStefano Zampini         csin_ds = PETSC_FALSE;
45156e683305SStefano Zampini         ncoarse_ds = all_procs;
45166e683305SStefano Zampini       }
45176e683305SStefano Zampini     }
451874e2c79eSStefano Zampini   }
45196e683305SStefano Zampini 
45206e683305SStefano Zampini   /*
45216e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
45226e683305SStefano Zampini     - we have not exceeded the number of levels requested
45236e683305SStefano Zampini     - we can actually subassemble the active processes
45246e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
45256e683305SStefano Zampini   */
45266e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
45276e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
45286e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
45296e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
45306e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4531f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
45322b510759SStefano Zampini     } else {
4533f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
4534c8587f34SStefano Zampini     }
4535c8587f34SStefano Zampini   }
45366e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
45376e683305SStefano Zampini   if (multilevel_allowed) {
45386e683305SStefano Zampini     ncoarse = ncoarse_ml;
45396e683305SStefano Zampini     csin = csin_ml;
454058da7f69SStefano Zampini     redist = PETSC_FALSE;
45416e683305SStefano Zampini   } else {
45426e683305SStefano Zampini     ncoarse = ncoarse_ds;
45436e683305SStefano Zampini     csin = csin_ds;
45446e683305SStefano Zampini   }
4545e7931f94SStefano Zampini 
4546abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
4547abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4548abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4549abbbba34SStefano Zampini 
4550abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
455122bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
455222bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
455322bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
455422bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4555b1ecc7b1SStefano Zampini #if 0
4556b9b85e73SStefano Zampini   {
4557b9b85e73SStefano Zampini     PetscViewer viewer;
4558b9b85e73SStefano Zampini     char filename[256];
4559b1ecc7b1SStefano Zampini     sprintf(filename,"local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4560b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4561b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4562b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
4563b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4564b9b85e73SStefano Zampini   }
4565b9b85e73SStefano Zampini #endif
4566e176bc59SStefano 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);
45676e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
45686e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45696e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4570abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4571abbbba34SStefano Zampini 
45726e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
45736e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
45746e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
45756e683305SStefano Zampini     const PetscInt         *idxs;
45766e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
45776e683305SStefano Zampini 
45786e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
45790be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
45806e683305SStefano Zampini     /* allocate space for temporary storage */
4581854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4582854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
45836e683305SStefano Zampini     /* allocate for IS array */
45846e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
45856e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
45866e683305SStefano Zampini     nis = nisdofs + nisneu;
4587854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
45886e683305SStefano Zampini     /* dofs splitting */
45896e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
45906e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
45916e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
45926e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
45936e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
45946e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
45956e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
45966e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
45976e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
45986e683305SStefano Zampini     }
45996e683305SStefano Zampini     /* neumann boundaries */
46006e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
46016e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
46026e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
46036e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
46046e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
46056e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
46066e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
46076e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
46086e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
46096e683305SStefano Zampini     }
46106e683305SStefano Zampini     /* free memory */
46116e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
46126e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
46136e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
46146e683305SStefano Zampini   } else {
46156e683305SStefano Zampini     nis = 0;
46166e683305SStefano Zampini     nisdofs = 0;
46176e683305SStefano Zampini     nisneu = 0;
46186e683305SStefano Zampini     isarray = NULL;
46196e683305SStefano Zampini   }
46206e683305SStefano Zampini   /* destroy no longer needed map */
46216e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
46226e683305SStefano Zampini 
46236e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
46246e683305SStefano Zampini   coarse_mat_is = NULL;
46256e683305SStefano Zampini   if (csin) {
46266e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
462774e2c79eSStefano Zampini       if (redist) {
462874e2c79eSStefano Zampini         PetscMPIInt rank;
4629779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
463074e2c79eSStefano Zampini 
463174e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
463258da7f69SStefano Zampini         spc = active_procs/ncoarse;
463358da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
4634779c1cceSStefano Zampini         if (im_active) {
4635779c1cceSStefano Zampini           destsize = 1;
463674e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
463774e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
463874e2c79eSStefano Zampini           } else {
463974e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
464074e2c79eSStefano Zampini           }
464174e2c79eSStefano Zampini         } else {
4642779c1cceSStefano Zampini           destsize = 0;
46436e683305SStefano Zampini         }
4644779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4645779c1cceSStefano Zampini       } else if (csin_type_simple) {
46466e683305SStefano Zampini         PetscMPIInt rank;
46476e683305SStefano Zampini         PetscInt    issize,isidx;
4648779c1cceSStefano Zampini 
46496e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
46506e683305SStefano Zampini         if (im_active) {
46516e683305SStefano Zampini           issize = 1;
46526e683305SStefano Zampini           isidx = (PetscInt)rank;
46536e683305SStefano Zampini         } else {
46546e683305SStefano Zampini           issize = 0;
46556e683305SStefano Zampini           isidx = -1;
46566e683305SStefano Zampini         }
46576e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4658779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
4659b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
46606e683305SStefano Zampini       }
4661779c1cceSStefano Zampini 
4662779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
4663779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
4664779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
4665779c1cceSStefano Zampini         PetscInt *coarse_candidates;
4666779c1cceSStefano Zampini         const PetscInt* tisindices;
4667779c1cceSStefano Zampini 
4668779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
4669779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
4670779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4671779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
4672779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
4673779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
4674779c1cceSStefano Zampini           }
4675779c1cceSStefano Zampini         }
4676779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
4677779c1cceSStefano Zampini 
4678779c1cceSStefano Zampini 
46796e683305SStefano Zampini         if (pcbddc->dbg_flag) {
46806e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
46816e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
46826e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
46836e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
4684779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
46856e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
46866e683305SStefano Zampini           }
46876e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
46886e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
46896e683305SStefano Zampini         }
46906e683305SStefano Zampini         /* shift the pattern on coarse candidates */
46916e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
46926e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
4693854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
46946e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
46956e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
46966e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
46976e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
46986e683305SStefano Zampini       }
46996e683305SStefano Zampini       if (pcbddc->dbg_flag) {
47006e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47016e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
47026e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
47036e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
47046e683305SStefano Zampini       }
4705779c1cceSStefano Zampini     }
47066e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
470753a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
470853a05cb3SStefano 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);
470953a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
471053a05cb3SStefano 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);
471153a05cb3SStefano Zampini     }
47126e683305SStefano Zampini   } else {
47136e683305SStefano Zampini     if (pcbddc->dbg_flag) {
47146e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47156e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
47166e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
47176e683305SStefano Zampini     }
47186e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
47196e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
47206e683305SStefano Zampini   }
47216e683305SStefano Zampini 
47226e683305SStefano Zampini   /* create local to global scatters for coarse problem */
472368457ee5SStefano Zampini   if (compute_vecs) {
47246e683305SStefano Zampini     PetscInt lrows;
47256e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
47266e683305SStefano Zampini     if (coarse_mat_is) {
47276e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
47286e683305SStefano Zampini     } else {
47296e683305SStefano Zampini       lrows = 0;
47306e683305SStefano Zampini     }
47316e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
47326e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
47336e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
47346e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
47356e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
47366e683305SStefano Zampini   }
47376e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
47386e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
4739c8587f34SStefano Zampini 
4740f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
4741f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
4742f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
4743f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
4744f9eb5b7dSStefano Zampini   } else {
4745f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
4746f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
4747c8587f34SStefano Zampini   }
4748c8587f34SStefano Zampini 
47496e683305SStefano Zampini   /* print some info if requested */
47506e683305SStefano Zampini   if (pcbddc->dbg_flag) {
47516e683305SStefano Zampini     if (!multilevel_allowed) {
47526e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47536e683305SStefano Zampini       if (multilevel_requested) {
47546e683305SStefano 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);
47556e683305SStefano Zampini       } else if (pcbddc->max_levels) {
47566e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
47576e683305SStefano Zampini       }
47586e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
47596e683305SStefano Zampini     }
47606e683305SStefano Zampini   }
47616e683305SStefano Zampini 
4762f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
47636e683305SStefano Zampini   if (coarse_mat_is) {
47646e683305SStefano Zampini     MatReuse coarse_mat_reuse;
47656a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
47666e683305SStefano Zampini     if (pcbddc->dbg_flag) {
47676e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
47686e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
47696e683305SStefano Zampini     }
4770f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
4771312be037SStefano Zampini       char prefix[256],str_level[16];
4772e604994aSStefano Zampini       size_t len;
47736e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
4774422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
4775c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
4776f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
47775f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
4778c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
47796e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
4780c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4781c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4782e604994aSStefano Zampini       /* prefix */
4783e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
4784e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4785e604994aSStefano Zampini       if (!pcbddc->current_level) {
4786e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4787e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
4788c8587f34SStefano Zampini       } else {
4789e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4790312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4791312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
479234d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4793312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4794e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
4795e604994aSStefano Zampini       }
4796e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
47973e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
47983e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
47993e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
48003e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
4801f9eb5b7dSStefano Zampini       /* allow user customization */
4802f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
48033e3c6dadSStefano Zampini     }
48043e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
480551bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
48063e3c6dadSStefano Zampini     if (nisdofs) {
48073e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
48083e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
48093e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
48103e3c6dadSStefano Zampini       }
48113e3c6dadSStefano Zampini     }
48123e3c6dadSStefano Zampini     if (nisneu) {
48133e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
48143e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
4815312be037SStefano Zampini     }
4816f9eb5b7dSStefano Zampini 
4817f9eb5b7dSStefano Zampini     /* get some info after set from options */
4818f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
4819f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
48204f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
48216e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
4822f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4823f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
4824f9eb5b7dSStefano Zampini     }
482539f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
48264f3a063dSStefano Zampini     if (isredundant) {
48274f3a063dSStefano Zampini       KSP inner_ksp;
48284f3a063dSStefano Zampini       PC  inner_pc;
48294f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
48304f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
48314f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
48324f3a063dSStefano Zampini     }
4833f9eb5b7dSStefano Zampini 
4834f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
4835fa7f1dd8SStefano Zampini     if (coarse_reuse) {
483681d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
4837fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
48386e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
4839fa7f1dd8SStefano Zampini     } else {
48406e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
4841fa7f1dd8SStefano Zampini     }
4842c8587f34SStefano Zampini     if (isbddc || isnn) {
484322bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
484470cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
4845b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
484622b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
48476e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
48486e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
48496e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
48506e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
485122b6e8a2SStefano Zampini           }
485270cf5478SStefano Zampini         }
485353a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
485470cf5478SStefano Zampini       } else {
485522bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
485622bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
485722bc73bbSStefano Zampini       }
485822bc73bbSStefano Zampini     } else {
48592e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
4860c8587f34SStefano Zampini     }
4861c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
4862c8587f34SStefano Zampini 
48633301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
48645a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
48653301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
48663301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
48673301b35fSStefano Zampini     }
48683301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
48693301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
48703301b35fSStefano Zampini     }
48713301b35fSStefano Zampini     if (pc->pmat->spd_set) {
48723301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
48733301b35fSStefano Zampini     }
48746e683305SStefano Zampini     /* set operators */
48755f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
48766e683305SStefano Zampini     if (pcbddc->dbg_flag) {
48776e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
48786e683305SStefano Zampini     }
48796e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
48806e683305SStefano Zampini     coarse_mat = 0;
48816e683305SStefano Zampini   }
48826e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
4883b1ecc7b1SStefano Zampini #if 0
4884b9b85e73SStefano Zampini   {
4885b9b85e73SStefano Zampini     PetscViewer viewer;
4886b9b85e73SStefano Zampini     char filename[256];
4887b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
4888b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
4889b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4890b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4891b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4892b9b85e73SStefano Zampini   }
4893b9b85e73SStefano Zampini #endif
4894c8587f34SStefano Zampini 
4895c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4896298c0119SStefano Zampini #if 0
4897c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4898c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
489998a51de6SStefano Zampini   }
4900298c0119SStefano Zampini #endif
4901*b0f5fe93SStefano Zampini   /* hack */
490298a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
490398a51de6SStefano Zampini     Vec crhs,csol;
490404708bb6SStefano Zampini 
4905f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4906f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
4907f347579bSStefano Zampini     if (!csol) {
49082a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4909f9eb5b7dSStefano Zampini     }
4910f347579bSStefano Zampini     if (!crhs) {
49112a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4912f347579bSStefano Zampini     }
4913*b0f5fe93SStefano Zampini   }
4914*b0f5fe93SStefano Zampini 
4915*b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
4916*b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
4917*b0f5fe93SStefano Zampini 
4918*b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
4919*b0f5fe93SStefano Zampini     ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-1,1.0,INSERT_VALUES);CHKERRQ(ierr);
4920*b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
4921*b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
4922*b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4923*b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4924*b0f5fe93SStefano Zampini     if (coarse_mat) {
4925*b0f5fe93SStefano Zampini       Vec         nullv;
4926*b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
4927*b0f5fe93SStefano Zampini       PetscInt    nl;
4928*b0f5fe93SStefano Zampini 
4929*b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
4930*b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
4931*b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
4932*b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
4933*b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
4934*b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
4935*b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
4936*b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
4937*b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
4938*b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
4939*b0f5fe93SStefano Zampini     }
4940*b0f5fe93SStefano Zampini   }
4941*b0f5fe93SStefano Zampini 
4942*b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
4943*b0f5fe93SStefano Zampini     PetscBool ispreonly;
4944*b0f5fe93SStefano Zampini 
4945*b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
4946*b0f5fe93SStefano Zampini       PetscBool isnull;
4947*b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
4948*b0f5fe93SStefano Zampini       if (isnull) {
4949*b0f5fe93SStefano Zampini         if (isbddc) {
4950*b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4951*b0f5fe93SStefano Zampini         } else {
4952*b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
4953*b0f5fe93SStefano Zampini         }
4954*b0f5fe93SStefano Zampini       } else {
4955*b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4956*b0f5fe93SStefano Zampini       }
4957*b0f5fe93SStefano Zampini     }
4958*b0f5fe93SStefano Zampini     /* setup coarse ksp */
4959*b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4960cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4961cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
49626e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4963c8587f34SStefano Zampini       KSP       check_ksp;
49642b510759SStefano Zampini       KSPType   check_ksp_type;
4965c8587f34SStefano Zampini       PC        check_pc;
49666e683305SStefano Zampini       Vec       check_vec,coarse_vec;
49676a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
49682b510759SStefano Zampini       PetscInt  its;
49696e683305SStefano Zampini       PetscBool compute_eigs;
49706e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
49716e683305SStefano Zampini       PetscInt  neigs;
49728e185a42SStefano Zampini       const char *prefix;
4973c8587f34SStefano Zampini 
49742b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
49756e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
4976422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
497723ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4978f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
49792b510759SStefano Zampini       if (ispreonly) {
49802b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
49816e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
49822b510759SStefano Zampini       } else {
4983cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
49846e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4985c8587f34SStefano Zampini       }
4986c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
49876e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
49886e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
49896e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4990a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4991a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4992a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4993a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4994c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4995c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4996c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4997c8587f34SStefano Zampini       /* create random vec */
49986e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
49996e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5000c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5001c8587f34SStefano Zampini       if (CoarseNullSpace) {
5002c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5003c8587f34SStefano Zampini       }
50046e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5005c8587f34SStefano Zampini       /* solve coarse problem */
50066e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5007c8587f34SStefano Zampini       if (CoarseNullSpace) {
50086e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5009c8587f34SStefano Zampini       }
5010cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
50116e683305SStefano Zampini       if (compute_eigs) {
5012854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5013854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
50146e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
50156e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
50166e683305SStefano Zampini         lambda_min = eigs_r[0];
50176e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
50186e683305SStefano Zampini           if (lambda_max>lambda_min) {
5019cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5020cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5021cbcc2c2aSStefano Zampini           }
5022c8587f34SStefano Zampini         }
5023c8587f34SStefano Zampini       }
5024cbcc2c2aSStefano Zampini 
5025c8587f34SStefano Zampini       /* check coarse problem residual error */
50266e683305SStefano Zampini       if (pcbddc->dbg_flag) {
50276e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
50286e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
50296e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5030c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
50316e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
50326e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5033c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5034779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
50356e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
50366e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
50376e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
50386e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5039*b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
5040*b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5041*b0f5fe93SStefano Zampini         }
50426e683305SStefano Zampini         if (compute_eigs) {
50436e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
5044deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5045c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
50466e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
50476e683305SStefano 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);
50486e683305SStefano Zampini           for (i=0;i<neigs;i++) {
50496e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5050c8587f34SStefano Zampini           }
50516e683305SStefano Zampini         }
50526e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
50536e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
50546e683305SStefano Zampini       }
5055c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
50566e683305SStefano Zampini       if (compute_eigs) {
50576e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
50586e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5059c8587f34SStefano Zampini       }
50606e683305SStefano Zampini     }
50616e683305SStefano Zampini   }
5062cbcc2c2aSStefano Zampini   /* print additional info */
5063cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
50646e683305SStefano Zampini     /* waits until all processes reaches this point */
50656e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5066cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5067cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5068cbcc2c2aSStefano Zampini   }
5069cbcc2c2aSStefano Zampini 
50702b510759SStefano Zampini   /* free memory */
5071c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5072fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5073c8587f34SStefano Zampini   PetscFunctionReturn(0);
5074c8587f34SStefano Zampini }
5075674ae819SStefano Zampini 
5076f34684f1SStefano Zampini #undef __FUNCT__
5077f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5078f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5079f34684f1SStefano Zampini {
5080f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5081f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5082f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5083dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5084dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
508573be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5086dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5087f34684f1SStefano Zampini   PetscErrorCode ierr;
5088f34684f1SStefano Zampini 
5089f34684f1SStefano Zampini   PetscFunctionBegin;
5090f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
50910e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
50920e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5093727cdba6SStefano Zampini   }
5094dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
50953bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5096dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5097dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5098dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5099dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5100dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5101dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
51020e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
51030e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
51040e6343abSStefano Zampini   }
5105dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5106dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5107dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5108dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5109dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5110f34684f1SStefano Zampini 
5111f34684f1SStefano Zampini   /* check numbering */
5112f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5113019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5114dc456d91SStefano Zampini     PetscInt    i;
5115b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5116f34684f1SStefano Zampini 
5117f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5118f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5119f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
51200fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
5121019a44ceSStefano Zampini     /* counter */
5122019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5123019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5124019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5125019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5126019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5127019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5128019a44ceSStefano Zampini 
5129f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5130f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5131727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5132f34684f1SStefano Zampini     }
5133f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5134f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5135f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5136e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5137e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5138e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5139e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5140f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5141019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5142f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5143019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
5144019a44ceSStefano Zampini         PetscInt owned = (PetscInt)(array[i]);
5145019a44ceSStefano Zampini         PetscInt neigh = (PetscInt)(array2[i]);
5146b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5147019a44ceSStefano 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);
5148f34684f1SStefano Zampini       }
5149f34684f1SStefano Zampini     }
5150019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5151b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5152f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5153f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5154f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5155f34684f1SStefano Zampini     }
5156f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5157f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5158e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5159e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5160f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5161f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5162b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5163ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5164ca8b9ea9SStefano Zampini 
5165ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
51663bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5167f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5168f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5169f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5170f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
51714bc2dc4bSStefano 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);
5172f34684f1SStefano Zampini       }
5173f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5174ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5175f34684f1SStefano Zampini     }
5176f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5177302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5178f34684f1SStefano Zampini   }
51798bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5180f34684f1SStefano Zampini   /* get back data */
5181f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5182f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5183674ae819SStefano Zampini   PetscFunctionReturn(0);
5184674ae819SStefano Zampini }
5185674ae819SStefano Zampini 
5186e456f2a8SStefano Zampini #undef __FUNCT__
5187e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5188a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5189e456f2a8SStefano Zampini {
5190e456f2a8SStefano Zampini   IS             localis_t;
5191a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5192e456f2a8SStefano Zampini   PetscScalar    *vals;
5193e456f2a8SStefano Zampini   PetscErrorCode ierr;
5194e456f2a8SStefano Zampini 
5195e456f2a8SStefano Zampini   PetscFunctionBegin;
5196a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5197e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5198854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5199e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5200e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5201a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5202a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
52031035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5204a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
52051035eff8SStefano Zampini   }
5206a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5207e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5208e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5209a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5210a7dc3881SStefano Zampini   /* now compute set in local ordering */
5211a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5212a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5213a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5214a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5215a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5216ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5217e456f2a8SStefano Zampini       lsize++;
5218e456f2a8SStefano Zampini     }
5219e456f2a8SStefano Zampini   }
5220854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5221a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5222ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5223e456f2a8SStefano Zampini       idxs[lsize++] = i;
5224e456f2a8SStefano Zampini     }
5225e456f2a8SStefano Zampini   }
5226a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5227a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5228e456f2a8SStefano Zampini   *localis = localis_t;
5229e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5230e456f2a8SStefano Zampini }
5231906d46d4SStefano Zampini 
5232906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5233906d46d4SStefano Zampini #undef __FUNCT__
5234906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5235906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5236906d46d4SStefano Zampini {
5237906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5238906d46d4SStefano Zampini   PetscErrorCode   ierr;
5239906d46d4SStefano Zampini 
5240906d46d4SStefano Zampini   PetscFunctionBegin;
5241906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5242906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5243906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5244906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5245906d46d4SStefano Zampini   PetscFunctionReturn(0);
5246906d46d4SStefano Zampini }
5247906d46d4SStefano Zampini 
5248906d46d4SStefano Zampini #undef __FUNCT__
5249906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5250906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5251906d46d4SStefano Zampini {
5252906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5253906d46d4SStefano Zampini   PetscErrorCode   ierr;
5254906d46d4SStefano Zampini 
5255906d46d4SStefano Zampini   PetscFunctionBegin;
5256906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5257906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5258906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5259906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5260906d46d4SStefano Zampini   PetscFunctionReturn(0);
5261906d46d4SStefano Zampini }
5262b96c3477SStefano Zampini 
5263b96c3477SStefano Zampini #undef __FUNCT__
5264b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
526508122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5266b96c3477SStefano Zampini {
5267a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5268b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5269b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5270a64f4aa4SStefano Zampini   Mat                 S_j;
5271b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
5272b96c3477SStefano Zampini   PetscBool           free_used_adj;
5273b96c3477SStefano Zampini   PetscErrorCode      ierr;
5274b96c3477SStefano Zampini 
5275b96c3477SStefano Zampini   PetscFunctionBegin;
5276b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
5277b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
527808122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
5279b96c3477SStefano Zampini     used_xadj = NULL;
5280b96c3477SStefano Zampini     used_adjncy = NULL;
5281b96c3477SStefano Zampini   } else {
528208122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
528308122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
528408122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
528508122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
5286b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
5287b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
5288b96c3477SStefano Zampini     } else {
52892fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
5290b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
5291b96c3477SStefano Zampini       PetscInt       nvtxs;
5292b96c3477SStefano Zampini 
52932fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
52942fffb893SStefano Zampini       if (flg_row) {
5295b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
5296b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
5297b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
5298b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
52992fffb893SStefano Zampini       } else {
53002fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
53012fffb893SStefano Zampini         used_xadj = NULL;
53022fffb893SStefano Zampini         used_adjncy = NULL;
53032fffb893SStefano Zampini       }
53042fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5305b96c3477SStefano Zampini     }
5306b96c3477SStefano Zampini   }
5307d5574798SStefano Zampini 
5308d5574798SStefano Zampini   /* setup sub_schurs data */
5309a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5310a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
5311a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
5312a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
531306a4e24aSStefano 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);
5314a64f4aa4SStefano Zampini   } else {
53156816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
531604708bb6SStefano Zampini     PetscBool isseqaij;
53175feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
53185feab87aSStefano Zampini       PetscInt n_vertices;
53195feab87aSStefano Zampini 
53205feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
53212034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
53225feab87aSStefano Zampini     }
532304708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
532404708bb6SStefano Zampini     if (!isseqaij) {
532504708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
532604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
532704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
532804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
532904708bb6SStefano Zampini       } else {
533004708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
533104708bb6SStefano Zampini       }
533204708bb6SStefano Zampini     }
533306a4e24aSStefano 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);
5334a64f4aa4SStefano Zampini   }
5335a64f4aa4SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5336b96c3477SStefano Zampini 
5337b96c3477SStefano Zampini   /* free adjacency */
5338b96c3477SStefano Zampini   if (free_used_adj) {
5339b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
5340b96c3477SStefano Zampini   }
5341b96c3477SStefano Zampini   PetscFunctionReturn(0);
5342b96c3477SStefano Zampini }
5343b96c3477SStefano Zampini 
5344b96c3477SStefano Zampini #undef __FUNCT__
5345b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
534608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
5347b96c3477SStefano Zampini {
5348b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5349b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5350b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5351b96c3477SStefano Zampini   PCBDDCGraph         graph;
5352b96c3477SStefano Zampini   PetscErrorCode      ierr;
5353b96c3477SStefano Zampini 
5354b96c3477SStefano Zampini   PetscFunctionBegin;
5355b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
535608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
53573301b35fSStefano Zampini     IS       verticesIS,verticescomm;
53583301b35fSStefano Zampini     PetscInt vsize,*idxs;
5359b96c3477SStefano Zampini 
5360b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
53613301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
53623301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
53633301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
53643301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
53653301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
5366b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
53677fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
53683301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
53693301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
5370b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5371b96c3477SStefano Zampini /*
5372b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
5373b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5374b96c3477SStefano Zampini     }
5375b96c3477SStefano Zampini */
5376b96c3477SStefano Zampini   } else {
5377b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
5378b96c3477SStefano Zampini   }
5379b96c3477SStefano Zampini 
5380b96c3477SStefano Zampini   /* sub_schurs init */
5381a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
5382a64f4aa4SStefano Zampini 
5383b96c3477SStefano Zampini   /* free graph struct */
538408122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
5385b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
5386b96c3477SStefano Zampini   }
5387b96c3477SStefano Zampini   PetscFunctionReturn(0);
5388b96c3477SStefano Zampini }
5389fa34dd3eSStefano Zampini 
5390fa34dd3eSStefano Zampini #undef __FUNCT__
5391fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
5392fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
5393fa34dd3eSStefano Zampini {
5394fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5395fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5396fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
5397fa34dd3eSStefano Zampini 
5398fa34dd3eSStefano Zampini   PetscFunctionBegin;
5399fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
5400fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
5401fa34dd3eSStefano Zampini     Mat            S_j,B0=NULL,B0_B=NULL;
5402fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
5403fa34dd3eSStefano Zampini     PetscScalar    norm,p0_check,*array,*array2;
5404fa34dd3eSStefano Zampini     PetscInt       i;
5405fa34dd3eSStefano Zampini 
5406fa34dd3eSStefano Zampini     /* B0 and B0_B */
5407fa34dd3eSStefano Zampini     if (zerodiag) {
5408fa34dd3eSStefano Zampini       IS       dummy;
5409fa34dd3eSStefano Zampini       PetscInt ii[2];
5410fa34dd3eSStefano Zampini 
5411fa34dd3eSStefano Zampini       ii[0] = 0;
5412fa34dd3eSStefano Zampini       ii[1] = pcbddc->B0_ncol;
5413fa34dd3eSStefano Zampini       ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,1,pcis->n,ii,pcbddc->B0_cols,pcbddc->B0_vals,&B0);CHKERRQ(ierr);
5414fa34dd3eSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&dummy);CHKERRQ(ierr);
5415fa34dd3eSStefano Zampini       ierr = MatGetSubMatrix(B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
5416fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
5417fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
5418fa34dd3eSStefano Zampini     }
5419fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
5420fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
5421fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
5422fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5423fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5424fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5425fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5426fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
5427fa34dd3eSStefano Zampini     /* S_j */
5428fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5429fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
5430fa34dd3eSStefano Zampini 
5431fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
5432fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
5433fa34dd3eSStefano Zampini     /* continuous in primal space */
5434fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
5435fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5436fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5437fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5438fa34dd3eSStefano Zampini     if (zerodiag) {
5439fa34dd3eSStefano Zampini       p0_check = array[pcbddc->local_primal_size-1];
5440fa34dd3eSStefano Zampini     } else {
5441fa34dd3eSStefano Zampini       p0_check = 0;
5442fa34dd3eSStefano Zampini     }
5443fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5444fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5445fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5446fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5447fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5448fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5449fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
5450fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
5451fa34dd3eSStefano Zampini 
5452fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
5453fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
5454fa34dd3eSStefano Zampini     /* local with Schur */
5455fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
5456fa34dd3eSStefano Zampini     if (zerodiag) {
5457fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
5458fa34dd3eSStefano Zampini       array[0] = p0_check;
5459fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5460fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5461fa34dd3eSStefano Zampini     }
5462fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
5463fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5464fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5465fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5466fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5467fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
5468fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5469fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5470fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
5471fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5472fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5473fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5474fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5475fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5476fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
5477fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
5478fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5479fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5480fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5481fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5482fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5483fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5484fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
5485fa34dd3eSStefano Zampini     if (zerodiag) {
5486fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
5487fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
5488fa34dd3eSStefano Zampini       pcbddc->benign_p0 = array[0];
5489fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5490fa34dd3eSStefano Zampini     } else {
5491fa34dd3eSStefano Zampini       pcbddc->benign_p0 = 0.;
5492fa34dd3eSStefano Zampini     }
5493fa34dd3eSStefano Zampini     /* BDDC */
5494fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
5495fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
5496fa34dd3eSStefano Zampini 
5497fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
5498fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
5499fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
5500fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
5501fa34dd3eSStefano Zampini     if (pcbddc->benign_p0_lidx >= 0) {
5502fa34dd3eSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0 error is %1.4e\n",PetscGlobalRank,PetscAbsScalar(pcbddc->benign_p0-p0_check));
5503fa34dd3eSStefano Zampini     }
5504fa34dd3eSStefano Zampini 
5505fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
5506fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
5507fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
5508fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5509fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0);CHKERRQ(ierr);
5510fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
5511fa34dd3eSStefano Zampini   }
5512fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
5513fa34dd3eSStefano Zampini }
5514