xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 5408967cf80e11a7f7b1797e0b68955f747486b2)
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__
9*5408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
10*5408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
11*5408967cSStefano Zampini {
12*5408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
13*5408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
14*5408967cSStefano Zampini   PetscErrorCode ierr;
15*5408967cSStefano Zampini 
16*5408967cSStefano Zampini   PetscFunctionBegin;
17*5408967cSStefano Zampini   if (zerodiag) {
18*5408967cSStefano Zampini     Mat            A;
19*5408967cSStefano Zampini     Vec            vec3_N;
20*5408967cSStefano Zampini     IS             dirIS = NULL;
21*5408967cSStefano Zampini     PetscScalar    *vals;
22*5408967cSStefano Zampini     const PetscInt *idxs;
23*5408967cSStefano Zampini     PetscInt       i,nz;
24*5408967cSStefano Zampini 
25*5408967cSStefano Zampini     /* p0 */
26*5408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
27*5408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
28*5408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
29*5408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
30*5408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.; /* TODO add quadrature */
31*5408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
32*5408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
33*5408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
34*5408967cSStefano Zampini     /* v_I */
35*5408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
36*5408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
37*5408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
38*5408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
39*5408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
40*5408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
41*5408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
42*5408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
43*5408967cSStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
44*5408967cSStefano Zampini     if (dirIS) {
45*5408967cSStefano Zampini       PetscInt n;
46*5408967cSStefano Zampini 
47*5408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
48*5408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
49*5408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
50*5408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
51*5408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
52*5408967cSStefano Zampini     }
53*5408967cSStefano Zampini     ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
54*5408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
55*5408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
56*5408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
57*5408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
58*5408967cSStefano Zampini     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
59*5408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
60*5408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
61*5408967cSStefano Zampini     if (PetscAbsScalar(vals[0]) > PETSC_SMALL) { /* TODO: should I add the A-norm in test? */
62*5408967cSStefano 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]));
63*5408967cSStefano Zampini     }
64*5408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
65*5408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
66*5408967cSStefano Zampini   }
67*5408967cSStefano Zampini 
68*5408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
69*5408967cSStefano Zampini   if (pcbddc->benign_saddle_point) {
70*5408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
71*5408967cSStefano Zampini     pcbddc->benign_p0 = -PetscGlobalRank;
72*5408967cSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
73*5408967cSStefano Zampini     pcbddc->benign_p0 = 1;
74*5408967cSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
75*5408967cSStefano Zampini     if (pcbddc->benign_p0_gidx >=0 && pcbddc->benign_p0 != -PetscGlobalRank) {
76*5408967cSStefano 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);
77*5408967cSStefano Zampini     }
78*5408967cSStefano Zampini   }
79*5408967cSStefano Zampini   PetscFunctionReturn(0);
80*5408967cSStefano Zampini }
81*5408967cSStefano Zampini 
82*5408967cSStefano Zampini #undef __FUNCT__
83339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
84339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
85339f8db1SStefano Zampini {
86339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
87339f8db1SStefano Zampini   IS             zerodiag;
88339f8db1SStefano Zampini   PetscInt       nz;
89339f8db1SStefano Zampini   PetscBool      sorted;
90339f8db1SStefano Zampini   PetscErrorCode ierr;
91339f8db1SStefano Zampini 
92339f8db1SStefano Zampini   PetscFunctionBegin;
93339f8db1SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
94339f8db1SStefano Zampini   ierr = PetscObjectReference((PetscObject)pcbddc->local_mat);CHKERRQ(ierr);
95339f8db1SStefano Zampini   pcbddc->benign_original_mat = pcbddc->local_mat;
96339f8db1SStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->benign_original_mat,&zerodiag);CHKERRQ(ierr);
97339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
98339f8db1SStefano Zampini   if (!sorted) {
99339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
100339f8db1SStefano Zampini   }
101339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
102339f8db1SStefano Zampini   if (nz) {
103339f8db1SStefano Zampini     IS                zerodiagc;
104339f8db1SStefano Zampini     PetscScalar       *array;
105339f8db1SStefano Zampini     const PetscInt    *idxs,*idxsc;
106339f8db1SStefano Zampini     PetscInt          i,n,*nnz;
107339f8db1SStefano Zampini 
108339f8db1SStefano Zampini     /* TODO: add check for shared dofs and raise error */
109339f8db1SStefano Zampini     ierr = MatGetLocalSize(pcbddc->benign_original_mat,&n,NULL);CHKERRQ(ierr);
110339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
111339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
112339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
113339f8db1SStefano Zampini     /* local change of basis for pressures */
114339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
115339f8db1SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->benign_original_mat),&pcbddc->benign_change);CHKERRQ(ierr);
116339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
117339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
118339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
119339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities */
120339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) nnz[idxs[i]] = 2; /* change on pressures */
121339f8db1SStefano Zampini     nnz[idxs[nz-1]] = nz; /* last local pressure dof: _0 set */
122339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
123339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
124339f8db1SStefano Zampini     /* set identity on velocities */
125339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
126339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
127339f8db1SStefano Zampini     }
128339f8db1SStefano Zampini     /* set change on pressures */
129339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) {
130339f8db1SStefano Zampini       PetscScalar vals[2];
131339f8db1SStefano Zampini       PetscInt    cols[2];
132339f8db1SStefano Zampini 
133339f8db1SStefano Zampini       /* TODO: add quadrature */
134339f8db1SStefano Zampini       cols[0] = idxs[i];
135339f8db1SStefano Zampini       cols[1] = idxs[nz-1];
136339f8db1SStefano Zampini       vals[0] = 1.;
137339f8db1SStefano Zampini       vals[1] = 1./nz;
138339f8db1SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+i,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
139339f8db1SStefano Zampini     }
140339f8db1SStefano Zampini     ierr = PetscMalloc1(nz,&array);CHKERRQ(ierr);
141339f8db1SStefano Zampini     for (i=0;i<nz-1;i++) array[i] = -1.;
142339f8db1SStefano Zampini     array[nz-1] = 1./nz;
143339f8db1SStefano Zampini     ierr = MatSetValues(pcbddc->benign_change,1,idxs+nz-1,nz,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
144339f8db1SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
145339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
146339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
147339f8db1SStefano Zampini     /* TODO: need optimization? */
148339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
149339f8db1SStefano Zampini     ierr = MatPtAP(pcbddc->benign_original_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
150339f8db1SStefano Zampini     /* store local and global idxs for p0 */
151339f8db1SStefano Zampini     pcbddc->benign_p0_lidx = idxs[nz-1];
152339f8db1SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,1,&idxs[nz-1],&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
153339f8db1SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
154339f8db1SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
155339f8db1SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
156339f8db1SStefano Zampini   } else { /* this is unlikely to happen but, just in case, destroy the empty IS */
157339f8db1SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
158339f8db1SStefano Zampini   }
159339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
160339f8db1SStefano Zampini   PetscFunctionReturn(0);
161339f8db1SStefano Zampini }
162339f8db1SStefano Zampini 
163339f8db1SStefano Zampini #undef __FUNCT__
164015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
165015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
166efc2fbd9SStefano Zampini {
167efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
168efc2fbd9SStefano Zampini   PetscErrorCode ierr;
169efc2fbd9SStefano Zampini 
170efc2fbd9SStefano Zampini   PetscFunctionBegin;
171efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
172efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
173c9ed8603SStefano Zampini     if (pcbddc->benign_p0_gidx >= 0) {
174efc2fbd9SStefano Zampini       ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,1,NULL,PETSC_OWN_POINTER,&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
175c9ed8603SStefano Zampini     } else {
176c9ed8603SStefano Zampini       ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,0,NULL,PETSC_OWN_POINTER,&pcbddc->benign_p0_gidx);CHKERRQ(ierr);
177c9ed8603SStefano Zampini     }
178efc2fbd9SStefano Zampini   }
179015636ebSStefano Zampini   if (get) { /* use SF to get values */
180efc2fbd9SStefano Zampini     PetscScalar *array;
181efc2fbd9SStefano Zampini 
182efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
183efc2fbd9SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,&pcbddc->benign_p0);CHKERRQ(ierr);
184efc2fbd9SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,&pcbddc->benign_p0);CHKERRQ(ierr);
185efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
186efc2fbd9SStefano Zampini   } else { /* use VecSetValue */
187c9ed8603SStefano Zampini     if (pcbddc->benign_p0_gidx >= 0) {
188efc2fbd9SStefano Zampini       ierr = VecSetValue(v,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
189c9ed8603SStefano Zampini     }
190efc2fbd9SStefano Zampini     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
191efc2fbd9SStefano Zampini     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
192efc2fbd9SStefano Zampini   }
193efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
194efc2fbd9SStefano Zampini }
195efc2fbd9SStefano Zampini 
196efc2fbd9SStefano Zampini #undef __FUNCT__
197c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
198c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
199c263805aSStefano Zampini {
200c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
201c263805aSStefano Zampini   PetscErrorCode ierr;
202c263805aSStefano Zampini 
203c263805aSStefano Zampini   PetscFunctionBegin;
204c263805aSStefano Zampini   /* TODO: add error checking
205c263805aSStefano Zampini     - avoid nested pop (or push) calls.
206c263805aSStefano Zampini     - cannot push before pop.
2071c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
208c263805aSStefano Zampini   */
209c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx < 0) {
210efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
211efc2fbd9SStefano Zampini   }
212c263805aSStefano Zampini   if (pop) {
213c263805aSStefano Zampini     const PetscInt    *cB0_cols;
214c263805aSStefano Zampini     PetscInt          cB0_ncol;
215c263805aSStefano Zampini     const PetscScalar *cB0_vals;
216c263805aSStefano Zampini 
217c263805aSStefano Zampini     /* extract B_0 */
218efc2fbd9SStefano Zampini     ierr = MatGetRow(pcbddc->local_mat,pcbddc->benign_p0_lidx,&cB0_ncol,&cB0_cols,&cB0_vals);CHKERRQ(ierr);
219c263805aSStefano Zampini     pcbddc->B0_ncol = cB0_ncol;
220c263805aSStefano Zampini     ierr = PetscFree2(pcbddc->B0_cols,pcbddc->B0_vals);CHKERRQ(ierr);
221c263805aSStefano Zampini     ierr = PetscMalloc2(cB0_ncol,&pcbddc->B0_cols,cB0_ncol,&pcbddc->B0_vals);CHKERRQ(ierr);
222c263805aSStefano Zampini     ierr = PetscMemcpy(pcbddc->B0_cols,cB0_cols,cB0_ncol*sizeof(PetscInt));CHKERRQ(ierr);
223c263805aSStefano Zampini     ierr = PetscMemcpy(pcbddc->B0_vals,cB0_vals,cB0_ncol*sizeof(PetscScalar));CHKERRQ(ierr);
224efc2fbd9SStefano Zampini     ierr = MatRestoreRow(pcbddc->local_mat,pcbddc->benign_p0_lidx,&cB0_ncol,&cB0_cols,&cB0_vals);CHKERRQ(ierr);
225c263805aSStefano Zampini     /* remove rows and cols from local problem */
226c263805aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
227efc2fbd9SStefano Zampini     ierr = MatZeroRowsColumns(pcbddc->local_mat,1,&pcbddc->benign_p0_lidx,1.,NULL,NULL);CHKERRQ(ierr);
228c263805aSStefano Zampini   } else { /* push */
229efc2fbd9SStefano Zampini     ierr = MatSetValues(pcbddc->local_mat,1,&pcbddc->benign_p0_lidx,pcbddc->B0_ncol,pcbddc->B0_cols,pcbddc->B0_vals,INSERT_VALUES);CHKERRQ(ierr);
230efc2fbd9SStefano Zampini     ierr = MatSetValues(pcbddc->local_mat,pcbddc->B0_ncol,pcbddc->B0_cols,1,&pcbddc->benign_p0_lidx,pcbddc->B0_vals,INSERT_VALUES);CHKERRQ(ierr);
231efc2fbd9SStefano Zampini     ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx,pcbddc->benign_p0_lidx,0.0,INSERT_VALUES);CHKERRQ(ierr);
232c263805aSStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
233c263805aSStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
234c263805aSStefano Zampini   }
235c263805aSStefano Zampini   PetscFunctionReturn(0);
236c263805aSStefano Zampini }
237c263805aSStefano Zampini 
238c263805aSStefano Zampini #undef __FUNCT__
239b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
24008122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
241b1b3d7a2SStefano Zampini {
242b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
24308122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
24408122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
24508122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
24608122e43SStefano Zampini   PetscScalar     *work,lwork;
24708122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
24808122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
24908122e43SStefano Zampini   PetscReal       *eigs,thresh;
2501b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
251f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
25208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25308122e43SStefano Zampini   PetscReal       *rwork;
25408122e43SStefano Zampini #endif
255b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
256b1b3d7a2SStefano Zampini 
257b1b3d7a2SStefano Zampini   PetscFunctionBegin;
25808122e43SStefano Zampini   if (!sub_schurs->use_mumps) {
25908122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
26008122e43SStefano Zampini   }
26108122e43SStefano Zampini 
26206a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
26306a4e24aSStefano 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);
26406a4e24aSStefano Zampini   }
26506a4e24aSStefano Zampini 
266fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
267fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
268fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
269fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
270fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
271fd14bc51SStefano Zampini   }
272fd14bc51SStefano Zampini 
273e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
274e496cd5dSStefano 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);
275e496cd5dSStefano Zampini   }
276e496cd5dSStefano Zampini 
27708122e43SStefano Zampini   /* max size of subsets */
27808122e43SStefano Zampini   mss = 0;
27908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
28008122e43SStefano Zampini     PetscInt subset_size;
281862806e4SStefano Zampini 
28208122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
28308122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
28408122e43SStefano Zampini   }
28508122e43SStefano Zampini 
28608122e43SStefano Zampini   /* min/max and threshold */
28708122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
288f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
28908122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
290f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
291f6f667cfSStefano Zampini   if (nmin) {
292f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
293f6f667cfSStefano Zampini   }
29408122e43SStefano Zampini 
29508122e43SStefano Zampini   /* allocate lapack workspace */
29608122e43SStefano Zampini   cum = cum2 = 0;
29708122e43SStefano Zampini   maxneigs = 0;
29808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
29908122e43SStefano Zampini     PetscInt n,subset_size;
300f6f667cfSStefano Zampini 
30108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
30208122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
3039162d606SStefano Zampini     cum += subset_size;
3049162d606SStefano Zampini     cum2 += subset_size*n;
30508122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
30608122e43SStefano Zampini   }
30708122e43SStefano Zampini   if (mss) {
3089ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
30908122e43SStefano Zampini       PetscBLASInt B_itype = 1;
31008122e43SStefano Zampini       PetscBLASInt B_N = mss;
3114c6709b3SStefano Zampini       PetscReal    zero = 0.0;
3124c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
31308122e43SStefano Zampini 
31408122e43SStefano Zampini       B_lwork = -1;
31508122e43SStefano Zampini       S = NULL;
31608122e43SStefano Zampini       St = NULL;
317a58a30b4SStefano Zampini       eigs = NULL;
318a58a30b4SStefano Zampini       eigv = NULL;
319a58a30b4SStefano Zampini       B_iwork = NULL;
320a58a30b4SStefano Zampini       B_ifail = NULL;
321d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
322d1710679SStefano Zampini       rwork = NULL;
323d1710679SStefano Zampini #endif
3248bec7fa6SStefano Zampini       thresh = 1.0;
32508122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
32608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
32708122e43SStefano 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));
32808122e43SStefano Zampini #else
32908122e43SStefano 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));
33008122e43SStefano Zampini #endif
33108122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
33208122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
33308122e43SStefano Zampini     } else {
33408122e43SStefano Zampini         /* TODO */
33508122e43SStefano Zampini     }
33608122e43SStefano Zampini   } else {
33708122e43SStefano Zampini     lwork = 0;
33808122e43SStefano Zampini   }
33908122e43SStefano Zampini 
34008122e43SStefano Zampini   nv = 0;
341d62866d3SStefano 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) */
342d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
34308122e43SStefano Zampini   }
3444c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
345f6f667cfSStefano Zampini   if (allocated_S_St) {
346f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
347f6f667cfSStefano Zampini   }
348f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
34908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
35008122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
35108122e43SStefano Zampini #endif
3529162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
3539162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
3549162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
35508122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
3569162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
35708122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
35808122e43SStefano Zampini 
35908122e43SStefano Zampini   maxneigs = 0;
36008122e43SStefano Zampini   cum = cum2 = cumarray = 0;
3619162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
3629162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
363d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
36408122e43SStefano Zampini     const PetscInt *idxs;
36508122e43SStefano Zampini 
366d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
36708122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
36808122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
36908122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
37008122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
3719162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
3729162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
37308122e43SStefano Zampini     }
37408122e43SStefano Zampini     cum2 = cum;
375d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
37608122e43SStefano Zampini   }
37708122e43SStefano Zampini 
37808122e43SStefano Zampini   if (mss) { /* multilevel */
37908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
38008122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
38108122e43SStefano Zampini   }
38208122e43SStefano Zampini 
38308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
38408122e43SStefano Zampini 
38508122e43SStefano Zampini     const PetscInt *idxs;
386f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
387862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
38808122e43SStefano Zampini     PetscBLASInt   B_N;
389aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
39008122e43SStefano Zampini 
391862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
392f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
393f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
3949ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
395aff50787SStefano Zampini         PetscInt j,k;
396aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
397aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
398aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
39908122e43SStefano Zampini         }
40008122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
401aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
402aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
403aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
404aff50787SStefano Zampini           }
40508122e43SStefano Zampini         }
40608122e43SStefano Zampini       } else {
40708122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
40808122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
40908122e43SStefano Zampini       }
4108bec7fa6SStefano Zampini     } else {
411f6f667cfSStefano Zampini       S = Sarray + cumarray;
412f6f667cfSStefano Zampini       St = Starray + cumarray;
4138bec7fa6SStefano Zampini     }
41408122e43SStefano Zampini 
415f6f667cfSStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
416aff50787SStefano Zampini     /* see if we can save some work */
417aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
418aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
419aff50787SStefano Zampini     }
420aff50787SStefano Zampini 
421aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
422aff50787SStefano Zampini       B_neigs = 0;
423aff50787SStefano Zampini     } else {
424aff50787SStefano Zampini       /* Threshold: this is an heuristic for edges */
425f6f667cfSStefano Zampini       thresh = pcbddc->mat_graph->count[idxs[0]]*pcbddc->adaptive_threshold;
426f6f667cfSStefano Zampini 
4279ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
42808122e43SStefano Zampini         PetscBLASInt B_itype = 1;
429f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
4304c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
4319552c7c7SStefano Zampini         PetscInt     nmin_s;
43208122e43SStefano Zampini 
433fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
4348bec7fa6SStefano 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]]);
435fd14bc51SStefano Zampini         }
436d16cbb6bSStefano Zampini 
43708122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
438d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
439d16cbb6bSStefano Zampini 
440d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
44108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
442f6f667cfSStefano 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));
44308122e43SStefano Zampini #else
444f6f667cfSStefano 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));
44508122e43SStefano Zampini #endif
446d16cbb6bSStefano Zampini         } else {
447d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
448d16cbb6bSStefano Zampini           B_IL = 1;
449d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
450d16cbb6bSStefano 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));
451d16cbb6bSStefano Zampini #else
452d16cbb6bSStefano 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));
453d16cbb6bSStefano Zampini #endif
454d16cbb6bSStefano Zampini         }
45508122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
45608122e43SStefano Zampini         if (B_ierr) {
45708122e43SStefano Zampini           if (B_ierr < 0 ) {
45808122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
45908122e43SStefano Zampini           } else if (B_ierr <= B_N) {
46008122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
46108122e43SStefano Zampini           } else {
4629552c7c7SStefano 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);
46308122e43SStefano Zampini           }
46408122e43SStefano Zampini         }
46508122e43SStefano Zampini 
46608122e43SStefano Zampini         if (B_neigs > nmax) {
467fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
468fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
469fd14bc51SStefano Zampini           }
470f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
47108122e43SStefano Zampini           B_neigs = nmax;
47208122e43SStefano Zampini         }
47308122e43SStefano Zampini 
4749552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
4759552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
47608122e43SStefano Zampini           PetscBLASInt B_neigs2;
47708122e43SStefano Zampini 
478f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
479f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
480fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
481fd14bc51SStefano 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);
482fd14bc51SStefano Zampini           }
4839ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
48408122e43SStefano Zampini             PetscInt j;
48508122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
48608122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
48708122e43SStefano Zampini             }
48808122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
48908122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
49008122e43SStefano Zampini             }
49108122e43SStefano Zampini           } else {
49208122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
49308122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
49408122e43SStefano Zampini           }
49508122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
49608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
497f6f667cfSStefano 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));
49808122e43SStefano Zampini #else
499f6f667cfSStefano 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));
50008122e43SStefano Zampini #endif
50108122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
50208122e43SStefano Zampini           B_neigs += B_neigs2;
50308122e43SStefano Zampini         }
50408122e43SStefano Zampini         if (B_ierr) {
50508122e43SStefano Zampini           if (B_ierr < 0 ) {
50608122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
50708122e43SStefano Zampini           } else if (B_ierr <= B_N) {
50808122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
50908122e43SStefano Zampini           } else {
5109552c7c7SStefano 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);
51108122e43SStefano Zampini           }
51208122e43SStefano Zampini         }
513fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
514ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
51508122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
51608122e43SStefano Zampini             if (eigs[j] == 0.0) {
517ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
51808122e43SStefano Zampini             } else {
519ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
520fd14bc51SStefano Zampini             }
52108122e43SStefano Zampini           }
52208122e43SStefano Zampini         }
52308122e43SStefano Zampini       } else {
52408122e43SStefano Zampini           /* TODO */
52508122e43SStefano Zampini       }
526aff50787SStefano Zampini     }
5278bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
5288bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
5299162d606SStefano Zampini     if (B_neigs) {
5309162d606SStefano 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);
531fd14bc51SStefano Zampini 
532fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
5339552c7c7SStefano Zampini         PetscInt ii;
5349552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
535ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
5369552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
537ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
538ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
539ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
540ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
541ac47001eSStefano Zampini #else
542ac47001eSStefano 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);
543ac47001eSStefano Zampini #endif
5449552c7c7SStefano Zampini           }
5459552c7c7SStefano Zampini         }
546fd14bc51SStefano Zampini       }
54708122e43SStefano Zampini #if 0
5489162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
54908122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
55008122e43SStefano Zampini         PetscScalar norm;
55108122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
5529162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
5539162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
55408122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
55508122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
55608122e43SStefano Zampini         } else {
55708122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
55808122e43SStefano Zampini         }
5599162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
560b1b3d7a2SStefano Zampini       }
561b1b3d7a2SStefano Zampini #endif
5629162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
5639162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
5649162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
5659162d606SStefano Zampini       cum++;
56608122e43SStefano Zampini     }
56708122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
56808122e43SStefano Zampini     /* shift for next computation */
56908122e43SStefano Zampini     cumarray += subset_size*subset_size;
57008122e43SStefano Zampini   }
571fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
572fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
573fd14bc51SStefano Zampini   }
57408122e43SStefano Zampini 
57508122e43SStefano Zampini   if (mss) {
57608122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
57708122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
578f6f667cfSStefano Zampini     /* destroy matrices (junk) */
579f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
580f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
58108122e43SStefano Zampini   }
582f6f667cfSStefano Zampini   if (allocated_S_St) {
583f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
584f6f667cfSStefano Zampini   }
585f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
58608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
58708122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
58808122e43SStefano Zampini #endif
58908122e43SStefano Zampini   if (pcbddc->dbg_flag) {
5901b968477SStefano Zampini     PetscInt maxneigs_r;
59108122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5929b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
59308122e43SStefano Zampini   }
59408122e43SStefano Zampini   PetscFunctionReturn(0);
59508122e43SStefano Zampini }
596b1b3d7a2SStefano Zampini 
597674ae819SStefano Zampini #undef __FUNCT__
598c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
599c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
600c8587f34SStefano Zampini {
601c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6028629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
603c8587f34SStefano Zampini   PetscErrorCode ierr;
604c8587f34SStefano Zampini 
605c8587f34SStefano Zampini   PetscFunctionBegin;
606f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
6075e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
608c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
609c8587f34SStefano Zampini 
610684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
6110fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
612684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
613c8587f34SStefano Zampini 
614c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
615b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
616c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
617c8587f34SStefano Zampini   }
618c8587f34SStefano Zampini 
6198629588bSStefano Zampini   /*
6208629588bSStefano Zampini      Setup local correction and local part of coarse basis.
6218629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
6228629588bSStefano Zampini   */
62347f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
6248629588bSStefano Zampini 
6258629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
6268629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
6278629588bSStefano Zampini 
6288629588bSStefano Zampini   /* free */
6298629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
630c8587f34SStefano Zampini   PetscFunctionReturn(0);
631c8587f34SStefano Zampini }
632c8587f34SStefano Zampini 
633c8587f34SStefano Zampini #undef __FUNCT__
634674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
635674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
636674ae819SStefano Zampini {
637674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
638674ae819SStefano Zampini   PetscErrorCode ierr;
639674ae819SStefano Zampini 
640674ae819SStefano Zampini   PetscFunctionBegin;
641674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
642674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
643674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
644674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
645785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
646674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
647f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
648f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
649785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
65063602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
65163602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
652674ae819SStefano Zampini   PetscFunctionReturn(0);
653674ae819SStefano Zampini }
654674ae819SStefano Zampini 
655674ae819SStefano Zampini #undef __FUNCT__
656674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
657674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
658674ae819SStefano Zampini {
659674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
660674ae819SStefano Zampini   PetscErrorCode ierr;
661674ae819SStefano Zampini 
662674ae819SStefano Zampini   PetscFunctionBegin;
663b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
664674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
665674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
666674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
667b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
668674ae819SStefano Zampini   PetscFunctionReturn(0);
669674ae819SStefano Zampini }
670674ae819SStefano Zampini 
671674ae819SStefano Zampini #undef __FUNCT__
672674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
673674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
674674ae819SStefano Zampini {
675674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
67606656605SStefano Zampini   PetscScalar    *array;
677674ae819SStefano Zampini   PetscErrorCode ierr;
678674ae819SStefano Zampini 
679674ae819SStefano Zampini   PetscFunctionBegin;
680674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
68158da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
68206656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
68306656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
68458da7f69SStefano Zampini   }
685674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
686674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
68715aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
68815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
689674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
690674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
691674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
69206656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
693674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
694674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
6958ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
696674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
697674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
698674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
699f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
700f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
701f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
702f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
703727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
7040e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
705f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
70670cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7076e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
70881d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
7090369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
7108b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
7118b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
71281d14e9dSStefano Zampini   ierr = PetscFree2(pcbddc->B0_cols,pcbddc->B0_vals);CHKERRQ(ierr);
713674ae819SStefano Zampini   PetscFunctionReturn(0);
714674ae819SStefano Zampini }
715674ae819SStefano Zampini 
716674ae819SStefano Zampini #undef __FUNCT__
717f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
718f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
7196bfb1811SStefano Zampini {
7206bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
7216bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
7226bfb1811SStefano Zampini   VecType        impVecType;
723019a44ceSStefano Zampini   PetscInt       n_constraints,n_R,old_size,n_benign;
7246bfb1811SStefano Zampini   PetscErrorCode ierr;
7256bfb1811SStefano Zampini 
7266bfb1811SStefano Zampini   PetscFunctionBegin;
727f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
728019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
729f4ddd8eeSStefano Zampini   }
730e7b262bdSStefano Zampini   /* get sizes */
731c9ed8603SStefano Zampini   n_benign = 0;
732c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) n_benign = 1;
733019a44ceSStefano Zampini   n_constraints = pcbddc->local_primal_size - n_benign - pcbddc->n_vertices;
734b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
7356bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
736e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
737e7b262bdSStefano Zampini   /* R nodes */
738e7b262bdSStefano Zampini   old_size = -1;
739e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
740e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
741e7b262bdSStefano Zampini   }
742e7b262bdSStefano Zampini   if (n_R != old_size) {
743e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
744e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
7456bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
7466bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
7476bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
7486bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
749e7b262bdSStefano Zampini   }
750e7b262bdSStefano Zampini   /* local primal dofs */
751e7b262bdSStefano Zampini   old_size = -1;
752e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
753e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
754e7b262bdSStefano Zampini   }
755e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
756e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
75783b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
758e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
7596bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
760e7b262bdSStefano Zampini   }
761e7b262bdSStefano Zampini   /* local explicit constraints */
762e7b262bdSStefano Zampini   old_size = -1;
763e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
764e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
765e7b262bdSStefano Zampini   }
766e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
767e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
76883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
76983b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
77083b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
77183b7ccabSStefano Zampini   }
7726bfb1811SStefano Zampini   PetscFunctionReturn(0);
7736bfb1811SStefano Zampini }
7746bfb1811SStefano Zampini 
7756bfb1811SStefano Zampini #undef __FUNCT__
77647f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
77747f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
77888ebb749SStefano Zampini {
77925084f0cSStefano Zampini   PetscErrorCode  ierr;
78025084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
78188ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
78288ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
783d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
78425084f0cSStefano Zampini   /* submatrices of local problem */
78580677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
786019a44ceSStefano Zampini   /* submatrices of benign trick */
787d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
78806656605SStefano Zampini   /* submatrices of local coarse problem */
78906656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
79025084f0cSStefano Zampini   /* working matrices */
79106656605SStefano Zampini   Mat             C_CR;
79225084f0cSStefano Zampini   /* additional working stuff */
79306656605SStefano Zampini   PC              pc_R;
794d12edf2fSStefano Zampini   Mat             F,B0 = NULL;
79506656605SStefano Zampini   PetscBool       isLU,isCHOL,isILU;
79606656605SStefano Zampini 
79725084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
79806656605SStefano Zampini   PetscScalar     *work;
79906656605SStefano Zampini   PetscInt        *idx_V_B;
800d12edf2fSStefano Zampini   PetscInt        n,n_vertices,n_constraints,n_benign,p0_lidx_I = 0;
80106656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
802b9d89cd5SStefano Zampini   PetscBool       unsymmetric_check;
80345a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
80488ebb749SStefano Zampini   MatType         impMatType;
80525084f0cSStefano Zampini   /* some shortcuts to scalars */
80606656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
80788ebb749SStefano Zampini 
80888ebb749SStefano Zampini   PetscFunctionBegin;
809c9ed8603SStefano Zampini   n_benign = 0;
810c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) n_benign = 1;
811b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
812019a44ceSStefano Zampini   n_constraints = pcbddc->local_primal_size - n_benign - n_vertices;
81388ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
814b371cd4fSStefano Zampini   n_B = pcis->n_B;
815b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
81688ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
81788ebb749SStefano Zampini 
81888ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
81988ebb749SStefano Zampini   impMatType = MATSEQDENSE;
82088ebb749SStefano Zampini 
82188ebb749SStefano Zampini   /* vertices in boundary numbering */
822785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
8230e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
82488ebb749SStefano Zampini   if (i != n_vertices) {
82522d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
82688ebb749SStefano Zampini   }
82788ebb749SStefano Zampini 
82806656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
829019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
83006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
83106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
83206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
83306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
83406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
83506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
83606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
83706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
83806656605SStefano Zampini 
83906656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
84006656605SStefano Zampini   /* allocate workspace */
84106656605SStefano Zampini   n = 0;
84206656605SStefano Zampini   if (n_constraints) {
84306656605SStefano Zampini     n += n_R*n_constraints;
84406656605SStefano Zampini   }
84506656605SStefano Zampini   if (n_vertices) {
84606656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
84780677318SStefano Zampini     n = PetscMax((n_R+n_B)*n_vertices,n);
84806656605SStefano Zampini   }
8493301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
85006656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
85106656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
85206656605SStefano Zampini   }
85306656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
85406656605SStefano Zampini 
85506656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
85606656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
85706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
85806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
85906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
86006656605SStefano Zampini   if (isLU || isILU || isCHOL) {
86106656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
862d62866d3SStefano Zampini   } else if (sub_schurs->reuse_mumps) {
863d62866d3SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
864d62866d3SStefano Zampini     MatFactorType type;
865d62866d3SStefano Zampini 
8666816873aSStefano Zampini     F = reuse_mumps->F;
8676816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
868d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
86906656605SStefano Zampini   } else {
87006656605SStefano Zampini     F = NULL;
87106656605SStefano Zampini   }
87206656605SStefano Zampini 
87388ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
87488ebb749SStefano Zampini   if (n_constraints) {
87506656605SStefano Zampini     Mat         M1,M2,M3;
87680677318SStefano Zampini     Mat         auxmat;
87706656605SStefano Zampini     IS          is_aux;
87880677318SStefano Zampini     PetscScalar *array,*array2;
87906656605SStefano Zampini 
880f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
88180677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
88288ebb749SStefano Zampini 
88325084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
88425084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
8858ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
88680677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
88788ebb749SStefano Zampini 
88880677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
88980677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
89006656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
89188ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
89206656605SStefano Zampini       const PetscScalar *row_cmat_values;
89306656605SStefano Zampini       const PetscInt    *row_cmat_indices;
89406656605SStefano Zampini       PetscInt          size_of_constraint,j;
89588ebb749SStefano Zampini 
89606656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
89706656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
89806656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
89906656605SStefano Zampini       }
90006656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
90106656605SStefano Zampini     }
90280677318SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
90306656605SStefano Zampini     if (F) {
90406656605SStefano Zampini       Mat B;
90506656605SStefano Zampini 
90606656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
90780677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
90806656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
90906656605SStefano Zampini     } else {
91080677318SStefano Zampini       PetscScalar *marr;
91180677318SStefano Zampini 
91280677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
91306656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
91406656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
91580677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*n_R);CHKERRQ(ierr);
91606656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
91706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
91806656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
91906656605SStefano Zampini       }
92080677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
92106656605SStefano Zampini     }
92280677318SStefano Zampini     if (!pcbddc->switch_static) {
92380677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
92480677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
92580677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
92680677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
92780677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*n_R);CHKERRQ(ierr);
92880677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
92980677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
93080677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
93180677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
93280677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
93380677318SStefano Zampini       }
93480677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
93580677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
93680677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
93780677318SStefano Zampini     } else {
93880677318SStefano Zampini       ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
93980677318SStefano Zampini       pcbddc->local_auxmat2 = local_auxmat2_R;
94025084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
94180677318SStefano Zampini     }
94280677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
94380677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
94480677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
94506656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
94606656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
94780677318SStefano Zampini     if (isCHOL) {
94880677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
94980677318SStefano Zampini     } else {
95025084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
95180677318SStefano Zampini     }
95280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
95306656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
95425084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
95525084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
95625084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
95780677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
95880677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
95980677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
96006656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
96106656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
962f4ddd8eeSStefano Zampini   }
96388ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
964d16cbb6bSStefano Zampini   if (n_benign) {
965d16cbb6bSStefano Zampini     IS        dummy;
966d16cbb6bSStefano Zampini     Mat       B0_R;
967d16cbb6bSStefano Zampini     PetscReal norm;
968d16cbb6bSStefano Zampini     PetscInt  ii[2];
969d16cbb6bSStefano Zampini 
970d16cbb6bSStefano Zampini     ii[0] = 0;
971d16cbb6bSStefano Zampini     ii[1] = pcbddc->B0_ncol;
972d16cbb6bSStefano Zampini     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,1,pcis->n,ii,pcbddc->B0_cols,pcbddc->B0_vals,&B0);CHKERRQ(ierr);
973d16cbb6bSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&dummy);CHKERRQ(ierr);
974d16cbb6bSStefano Zampini     ierr = MatGetSubMatrix(B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
975d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
976d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
977d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
978d16cbb6bSStefano Zampini     }
979d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
980d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
981d16cbb6bSStefano Zampini   }
982d16cbb6bSStefano Zampini 
98388ebb749SStefano Zampini   if (n_vertices) {
98406656605SStefano Zampini     IS is_aux;
9853a50541eSStefano Zampini 
9866816873aSStefano Zampini     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
9876816873aSStefano Zampini       IS tis;
9886816873aSStefano Zampini 
9896816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
9906816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
9916816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
9926816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
9936816873aSStefano Zampini     } else {
9943a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
9956816873aSStefano Zampini     }
9969577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
9979577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
99804708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
999019a44ceSStefano Zampini     if (n_benign) {
1000019a44ceSStefano Zampini       IS dummy;
1001019a44ceSStefano Zampini 
1002019a44ceSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&dummy);CHKERRQ(ierr);
1003019a44ceSStefano Zampini       ierr = MatGetSubMatrix(B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1004019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1005019a44ceSStefano Zampini     }
100625084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
100788ebb749SStefano Zampini   }
100888ebb749SStefano Zampini 
100988ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1010f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
101106656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
101206656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
101306656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
101406656605SStefano Zampini     }
1015f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
101606656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
101706656605SStefano Zampini       PetscScalar *marray;
101806656605SStefano Zampini 
101906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
102006656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1021f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1022f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1023f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1024f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1025f4ddd8eeSStefano Zampini     }
1026f4ddd8eeSStefano Zampini   }
102706656605SStefano Zampini 
1028f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
102906656605SStefano Zampini     PetscScalar *marray;
103088ebb749SStefano Zampini 
103106656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
10328eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
103306656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
103488ebb749SStefano Zampini     }
10353301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
103606656605SStefano Zampini       n *= 2;
103788ebb749SStefano Zampini     }
103806656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
103906656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
104006656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
10418eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
104206656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
104306656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
104488ebb749SStefano Zampini     }
10453301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
104606656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
10478eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
104806656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
104906656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
105088ebb749SStefano Zampini       }
105188ebb749SStefano Zampini     } else {
1052c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1053c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
10541b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1055c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1056c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1057c0553b1fSStefano Zampini       }
105888ebb749SStefano Zampini     }
105906656605SStefano Zampini   }
1060019a44ceSStefano Zampini 
106106656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
1062d12edf2fSStefano Zampini   if (n_benign && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1063d12edf2fSStefano Zampini     const PetscInt *idxs;
1064d12edf2fSStefano Zampini 
1065d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1066d12edf2fSStefano Zampini     ierr = PetscFindInt(pcbddc->benign_p0_lidx,pcis->n-pcis->n_B,idxs,&p0_lidx_I);CHKERRQ(ierr);
1067d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1068d12edf2fSStefano Zampini   }
1069d16cbb6bSStefano Zampini 
107006656605SStefano Zampini   /* vertices */
107106656605SStefano Zampini   if (n_vertices) {
107216f15bc4SStefano Zampini 
107304708bb6SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
107404708bb6SStefano Zampini 
107516f15bc4SStefano Zampini     if (n_R) {
107606656605SStefano Zampini       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
107706656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
107816f15bc4SStefano Zampini       PetscScalar  *x,*y;
107904708bb6SStefano Zampini       PetscBool    isseqaij;
108006656605SStefano Zampini 
108121eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
108206656605SStefano Zampini       ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
108304708bb6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
10846816873aSStefano Zampini       if (F) { /* TODO could be optimized for symmetric problems */
108506656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
108606656605SStefano Zampini       } else {
108706656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
108806656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
108906656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
109006656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
109106656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
109206656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
109306656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
109406656605SStefano Zampini         }
109506656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
109606656605SStefano Zampini       }
109780677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
109806656605SStefano Zampini       /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
109906656605SStefano Zampini       if (n_constraints) {
110006656605SStefano Zampini         Mat B;
110180677318SStefano Zampini 
1102b3d85658SStefano Zampini         ierr = PetscMemzero(work+n_R*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
110380677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
110480677318SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
110580677318SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+n_R*n_vertices+i*n_B);CHKERRQ(ierr);
110680677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
110780677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
110880677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
110980677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
111080677318SStefano Zampini         }
111180677318SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
111280677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
111380677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
111406656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
111580677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
111606656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
111706656605SStefano Zampini         ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
111806656605SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
111906656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
112006656605SStefano Zampini       }
112104708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
112204708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
112304708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
112404708bb6SStefano Zampini       }
112506656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
112680677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
112706656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
112806656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
112906656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
113006656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
113106656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
113206656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
113306656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1134d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1135019a44ceSStefano Zampini     } else {
1136d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1137d16cbb6bSStefano Zampini     }
1138d16cbb6bSStefano Zampini     if (n_benign) {
1139019a44ceSStefano Zampini       const PetscScalar *vals;
1140019a44ceSStefano Zampini       const PetscInt    *idxs;
1141019a44ceSStefano Zampini       PetscInt          n,j;
1142019a44ceSStefano Zampini 
1143019a44ceSStefano Zampini       ierr = MatGetRow(B0_V,0,&n,&idxs,&vals);CHKERRQ(ierr);
1144d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
1145d16cbb6bSStefano Zampini         coarse_submat_vals[(pcbddc->local_primal_size-1)*pcbddc->local_primal_size+idxs[j]] = vals[j];
1146d16cbb6bSStefano Zampini         coarse_submat_vals[(idxs[j]+1)*pcbddc->local_primal_size-1] = vals[j];
1147019a44ceSStefano Zampini       }
1148019a44ceSStefano Zampini       ierr = MatRestoreRow(B0_V,0,&n,&idxs,&vals);CHKERRQ(ierr);
114916f15bc4SStefano Zampini     }
115021eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1151d16cbb6bSStefano Zampini 
115206656605SStefano Zampini     /* coarse basis functions */
115306656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
115416f15bc4SStefano Zampini       PetscScalar *y;
115516f15bc4SStefano Zampini 
115606656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
115706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
115806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
115906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
116006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
116106656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
116206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
116306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
116406656605SStefano Zampini 
116506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
116606656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
116706656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
116806656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
116906656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
117006656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1171a0aff763SStefano Zampini         if (n_benign) y[n_D*i+p0_lidx_I] = 0.0;
117206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
117306656605SStefano Zampini       }
117406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
117506656605SStefano Zampini     }
117604708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
117704708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
117806656605SStefano Zampini   }
117906656605SStefano Zampini 
118006656605SStefano Zampini   if (n_constraints) {
118106656605SStefano Zampini     Mat B;
118206656605SStefano Zampini 
118306656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
118406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
118580677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
118606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
118706656605SStefano Zampini     if (n_vertices) {
118880677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
118980677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
119080677318SStefano Zampini       } else {
119180677318SStefano Zampini         Mat S_VCt;
119280677318SStefano Zampini 
119380677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
119480677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
119580677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
119680677318SStefano Zampini       }
119706656605SStefano Zampini     }
119806656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
119906656605SStefano Zampini     /* coarse basis functions */
120006656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
120106656605SStefano Zampini       PetscScalar *y;
120206656605SStefano Zampini 
120306656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
120406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
120506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
120606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
120706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
120806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
120906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
121006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
121106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
121206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
121306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
121406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
121506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1216d16cbb6bSStefano Zampini         if (n_benign) y[n_D*(i+n_vertices)+p0_lidx_I] = 0.0;
121706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
121806656605SStefano Zampini       }
121906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
122006656605SStefano Zampini     }
122106656605SStefano Zampini   }
122280677318SStefano Zampini   if (n_constraints) {
122380677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
122480677318SStefano Zampini   }
122506656605SStefano Zampini 
1226019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1227019a44ceSStefano Zampini 
122806656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
12293301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
123006656605SStefano Zampini 
123106656605SStefano Zampini     if (n_constraints) {
123216f15bc4SStefano Zampini       Mat S_CCT,B_C;
123306656605SStefano Zampini 
123480677318SStefano Zampini       /* this is a lazy thing */
123580677318SStefano Zampini       ierr = MatConvert(C_CR,impMatType,MAT_REUSE_MATRIX,&C_CR);CHKERRQ(ierr);
123606656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
123706656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
123806656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
123916f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
124006656605SStefano Zampini       if (n_vertices) {
124116f15bc4SStefano Zampini         Mat B_V,S_VCT;
124206656605SStefano Zampini 
124306656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
124406656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
124506656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
124606656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
124716f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
124806656605SStefano Zampini       }
124906656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
125080677318SStefano Zampini     } else { /* if there are no constraints, reset work */
125180677318SStefano Zampini       ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
125206656605SStefano Zampini     }
125316f15bc4SStefano Zampini     if (n_vertices && n_R) {
125406656605SStefano Zampini       Mat          A_VRT;
125580677318SStefano Zampini       PetscScalar  *marray;
125606656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
125706656605SStefano Zampini 
125880677318SStefano Zampini       ierr = MatTranspose(A_VR,MAT_INITIAL_MATRIX,&A_VRT);CHKERRQ(ierr);
125980677318SStefano Zampini       ierr = MatConvert(A_VRT,impMatType,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
126080677318SStefano Zampini       ierr = MatDenseGetArray(A_VRT,&marray);CHKERRQ(ierr);
126106656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
126280677318SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,marray,&B_one,work,&B_one));
126380677318SStefano Zampini       ierr = MatDenseRestoreArray(A_VRT,&marray);CHKERRQ(ierr);
126416f15bc4SStefano Zampini       ierr = MatDestroy(&A_VRT);CHKERRQ(ierr);
126506656605SStefano Zampini     }
126606656605SStefano Zampini 
126706656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
126806656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
126906656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
127006656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
127106656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
127206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
127306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
127406656605SStefano Zampini       }
127506656605SStefano Zampini     } else {
127606656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
127706656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
127806656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
127906656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
128006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
128106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
128206656605SStefano Zampini       }
128306656605SStefano Zampini     }
128406656605SStefano Zampini     /* coarse basis functions */
128506656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
128606656605SStefano Zampini       PetscScalar *y;
128706656605SStefano Zampini 
128806656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
128906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
129006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
129106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
129206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
129306656605SStefano Zampini       if (i<n_vertices) {
129406656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
129506656605SStefano Zampini       }
129606656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
129706656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
129806656605SStefano Zampini 
129906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
130006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
130106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
130206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
130306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
130406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
130506656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
130606656605SStefano Zampini       }
130706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
130806656605SStefano Zampini     }
130906656605SStefano Zampini   }
1310d62866d3SStefano Zampini   /* free memory */
131188ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
131206656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
131306656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
131406656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
131506656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
1316d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
1317d62866d3SStefano Zampini   if (n_vertices) {
1318d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1319d62866d3SStefano Zampini   }
1320d62866d3SStefano Zampini   if (n_constraints) {
1321d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1322d62866d3SStefano Zampini   }
132388ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
132488ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
132588ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1326d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
132788ebb749SStefano Zampini     Mat         coarse_sub_mat;
132825084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
132988ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
133088ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
133188ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
13328bec7fa6SStefano Zampini     Mat         C_B,CPHI;
13338bec7fa6SStefano Zampini     IS          is_dummy;
13348bec7fa6SStefano Zampini     Vec         mones;
133588ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
133688ebb749SStefano Zampini     PetscReal   real_value;
133788ebb749SStefano Zampini 
133888ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
133988ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
134088ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
134188ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
134288ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
134388ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1344c0553b1fSStefano Zampini     if (unsymmetric_check) {
134588ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
134688ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
134788ebb749SStefano Zampini     }
134888ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
134988ebb749SStefano Zampini 
135025084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
13513301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
135225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1353c0553b1fSStefano Zampini     if (unsymmetric_check) {
135488ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
135588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
135688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
135788ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
135888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
135988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
136088ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
136188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
136288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
136388ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
136488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
136588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
136688ebb749SStefano Zampini     } else {
136788ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
136888ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
136988ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
137088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
137188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
137288ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
137388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
137488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
137588ebb749SStefano Zampini     }
137688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
137788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
137888ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
137988ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
1380d12edf2fSStefano Zampini     if (n_benign) {
1381d12edf2fSStefano Zampini       Mat B0_I,B0_B,B0_BPHI,B0_IPHI;
1382d12edf2fSStefano Zampini       PetscScalar *data,*data2;
1383d12edf2fSStefano Zampini 
1384d12edf2fSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,1,0,1,&is_dummy);CHKERRQ(ierr);
1385d12edf2fSStefano Zampini       ierr = MatGetSubMatrix(B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
1386d12edf2fSStefano Zampini       ierr = MatGetSubMatrix(B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
1387d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
1388d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
1389d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
1390d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
1391d12edf2fSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
1392d16cbb6bSStefano Zampini         data[(pcbddc->local_primal_size-1)*pcbddc->local_primal_size+i] += data2[i];
1393d16cbb6bSStefano Zampini         data[(i+1)*pcbddc->local_primal_size-1] += data2[i];
1394d12edf2fSStefano Zampini       }
1395d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
1396d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
1397d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
1398d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1399d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
1400d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
1401d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
1402d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1403d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
1404d12edf2fSStefano Zampini     }
1405d12edf2fSStefano Zampini #if 0
1406d12edf2fSStefano Zampini   {
1407d12edf2fSStefano Zampini     PetscViewer viewer;
1408d12edf2fSStefano Zampini     char filename[256];
1409d12edf2fSStefano Zampini     sprintf(filename,"proj_local_coarse_mat%d.m",PetscGlobalRank);
1410d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1411d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1412d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
1413d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1414d12edf2fSStefano Zampini   }
1415d12edf2fSStefano Zampini #endif
141681d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
14178bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
14180fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
141906656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
14208bec7fa6SStefano Zampini 
14218bec7fa6SStefano Zampini     /* check constraints */
1422d12edf2fSStefano Zampini     if (!n_benign) {
14238bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
14248bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
14258bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
14268bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
14278bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
14288bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
14298bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1430bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1431c0553b1fSStefano Zampini       if (unsymmetric_check) {
1432bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1433bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1434bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1435bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1436bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
143788ebb749SStefano Zampini       }
14388bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
14398bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
14408bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
14418bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
1442d12edf2fSStefano Zampini     }
144325084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
144488ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
144588ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
144688ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
144788ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
144888ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
144988ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
145088ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
145188ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
145288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
145388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1454c0553b1fSStefano Zampini     if (unsymmetric_check) {
145588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
145688ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
145788ebb749SStefano Zampini     }
145888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
145988ebb749SStefano Zampini   }
1460d12edf2fSStefano Zampini   ierr = MatDestroy(&B0);CHKERRQ(ierr);
14618629588bSStefano Zampini   /* get back data */
14628629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
146388ebb749SStefano Zampini   PetscFunctionReturn(0);
146488ebb749SStefano Zampini }
146588ebb749SStefano Zampini 
146688ebb749SStefano Zampini #undef __FUNCT__
1467d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1468d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
1469aa0d41d4SStefano Zampini {
1470d65f70fdSStefano Zampini   Mat            *work_mat;
1471d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1472d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1473d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1474aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1475aa0d41d4SStefano Zampini 
1476aa0d41d4SStefano Zampini   PetscFunctionBegin;
1477d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1478d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1479d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1480d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1481aa0d41d4SStefano Zampini 
1482d65f70fdSStefano Zampini   if (!rsorted) {
1483906d46d4SStefano Zampini     const PetscInt *idxs;
1484906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
1485aa0d41d4SStefano Zampini 
1486d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1487d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1488d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1489d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1490aa0d41d4SStefano Zampini     }
1491d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1492d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1493d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1494d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1495aa0d41d4SStefano Zampini     }
1496d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1497d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1498d65f70fdSStefano Zampini   } else {
1499d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1500d65f70fdSStefano Zampini     isrow_s = isrow;
1501aa0d41d4SStefano Zampini   }
1502906d46d4SStefano Zampini 
1503d65f70fdSStefano Zampini   if (!csorted) {
1504d65f70fdSStefano Zampini     if (isrow == iscol) {
1505d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1506d65f70fdSStefano Zampini       iscol_s = isrow_s;
1507d65f70fdSStefano Zampini     } else {
1508d65f70fdSStefano Zampini       const PetscInt *idxs;
1509d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1510906d46d4SStefano Zampini 
1511d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1512d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1513d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1514d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1515d65f70fdSStefano Zampini       }
1516d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1517d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1518d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1519d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1520d65f70fdSStefano Zampini       }
1521d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1522d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1523d65f70fdSStefano Zampini     }
1524d65f70fdSStefano Zampini   } else {
1525d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1526d65f70fdSStefano Zampini     iscol_s = iscol;
1527d65f70fdSStefano Zampini   }
1528d65f70fdSStefano Zampini 
1529d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1530d65f70fdSStefano Zampini 
1531d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1532906d46d4SStefano Zampini     Mat      new_mat;
1533d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1534906d46d4SStefano Zampini 
1535d65f70fdSStefano Zampini     if (!rsorted) {
1536d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1537d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1538d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1539d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1540906d46d4SStefano Zampini       }
1541d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1542d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1543d65f70fdSStefano Zampini     } else {
1544d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1545906d46d4SStefano Zampini     }
1546d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1547d65f70fdSStefano Zampini 
1548d65f70fdSStefano Zampini     if (!csorted) {
1549d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1550d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1551d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1552d65f70fdSStefano Zampini       } else {
1553d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1554d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1555d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1556d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1557d65f70fdSStefano Zampini         }
1558d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1559d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1560d65f70fdSStefano Zampini       }
1561d65f70fdSStefano Zampini     } else {
1562d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1563d65f70fdSStefano Zampini     }
1564d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1565d65f70fdSStefano Zampini 
1566d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1567d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1568d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1569d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1570d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1571d65f70fdSStefano Zampini   }
1572d65f70fdSStefano Zampini 
1573d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1574d65f70fdSStefano Zampini   *B = work_mat[0];
1575d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1576d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1577d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1578d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1579d65f70fdSStefano Zampini }
1580d65f70fdSStefano Zampini 
1581d65f70fdSStefano Zampini #undef __FUNCT__
15825e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
15835e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1584aa0d41d4SStefano Zampini {
1585aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
15865e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1587d65f70fdSStefano Zampini   Mat            new_mat;
15885e8657edSStefano Zampini   IS             is_local,is_global;
1589d65f70fdSStefano Zampini   PetscInt       local_size;
1590d65f70fdSStefano Zampini   PetscBool      isseqaij;
1591aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1592aa0d41d4SStefano Zampini 
1593aa0d41d4SStefano Zampini   PetscFunctionBegin;
1594aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
15955e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
15965e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1597b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
1598aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1599d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
1600aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1601906d46d4SStefano Zampini 
1602906d46d4SStefano Zampini   /* check */
1603906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
1604906d46d4SStefano Zampini     Vec       x,x_change;
1605906d46d4SStefano Zampini     PetscReal error;
1606906d46d4SStefano Zampini 
16075e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1608906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
16095e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
1610e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1611e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1612d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
1613e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1614e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1615906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1616906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1617906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1618906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1619906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
1620906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1621906d46d4SStefano Zampini   }
1622906d46d4SStefano Zampini 
162322d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
16249b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
162522d5777bSStefano Zampini   if (isseqaij) {
1626d65f70fdSStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1627aa0d41d4SStefano Zampini   } else {
1628aa0d41d4SStefano Zampini     Mat work_mat;
1629aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1630d65f70fdSStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
1631aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
1632aa0d41d4SStefano Zampini   }
16333301b35fSStefano Zampini   if (matis->A->symmetric_set) {
16343301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
1635e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
16363301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
1637e496cd5dSStefano Zampini #endif
16383301b35fSStefano Zampini   }
163945a1bb75SStefano Zampini   /*
164045a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1641d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
164245a1bb75SStefano Zampini   */
1643d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
1644aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
1645aa0d41d4SStefano Zampini }
1646aa0d41d4SStefano Zampini 
1647aa0d41d4SStefano Zampini #undef __FUNCT__
1648a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
16498ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
1650a64d13efSStefano Zampini {
1651a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
1652a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1653d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
165453892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
16553a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
16563a50541eSStefano Zampini   PetscInt        vbs,bs;
16576816873aSStefano Zampini   PetscBT         bitmask=NULL;
1658a64d13efSStefano Zampini   PetscErrorCode  ierr;
1659a64d13efSStefano Zampini 
1660a64d13efSStefano Zampini   PetscFunctionBegin;
1661b23d619eSStefano Zampini   /*
1662b23d619eSStefano Zampini     No need to setup local scatters if
1663b23d619eSStefano Zampini       - primal space is unchanged
1664b23d619eSStefano Zampini         AND
1665b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
1666b23d619eSStefano Zampini         AND
1667b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
1668b23d619eSStefano Zampini   */
1669b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
1670f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
1671f4ddd8eeSStefano Zampini   }
1672f4ddd8eeSStefano Zampini   /* destroy old objects */
1673f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1674f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1675f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1676a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
1677b371cd4fSStefano Zampini   n_B = pcis->n_B;
1678b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
1679b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
16803a50541eSStefano Zampini 
1681a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
16826816873aSStefano Zampini 
168353892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
16846816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
1685854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
1686a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
1687a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
16880e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
1689a64d13efSStefano Zampini     }
1690a64d13efSStefano Zampini 
1691a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
16924641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
16936816873aSStefano Zampini         idx_R_local[n_R++] = i;
1694a64d13efSStefano Zampini       }
1695a64d13efSStefano Zampini     }
169653892102SStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
16976816873aSStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
16986816873aSStefano Zampini 
169953892102SStefano Zampini     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
170053892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
17016816873aSStefano Zampini   }
17023a50541eSStefano Zampini 
17033a50541eSStefano Zampini   /* Block code */
17043a50541eSStefano Zampini   vbs = 1;
17053a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
17063a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
17073a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
17083a50541eSStefano Zampini     PetscInt  *vary;
1709d3df7717SStefano Zampini     if (!sub_schurs->reuse_mumps) {
1710785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
17113a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
1712d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
1713d3df7717SStefano 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 */
17140e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
1715d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
17163a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
17173a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
17183a50541eSStefano Zampini           break;
17193a50541eSStefano Zampini         }
17203a50541eSStefano Zampini       }
1721d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
1722d3df7717SStefano Zampini     } else {
1723d3df7717SStefano Zampini       /* Verify directly the R set */
1724d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
1725d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
1726d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
1727d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
1728d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
1729d3df7717SStefano Zampini             break;
1730d3df7717SStefano Zampini           }
1731d3df7717SStefano Zampini         }
1732d3df7717SStefano Zampini       }
1733d3df7717SStefano Zampini     }
17343a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
17353a50541eSStefano Zampini       vbs = bs;
17363a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
17373a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
17383a50541eSStefano Zampini       }
17393a50541eSStefano Zampini     }
17403a50541eSStefano Zampini   }
17413a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
174253892102SStefano Zampini   if (sub_schurs->reuse_mumps) {
174353892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
174453892102SStefano Zampini 
174553892102SStefano Zampini     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
174653892102SStefano Zampini     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
174753892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
174853892102SStefano Zampini     reuse_mumps->is_R = pcbddc->is_R_local;
174953892102SStefano Zampini   } else {
17503a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
175153892102SStefano Zampini   }
1752a64d13efSStefano Zampini 
1753a64d13efSStefano Zampini   /* print some info if requested */
1754a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
1755c9ed8603SStefano Zampini     PetscInt benign = 0;
1756019a44ceSStefano Zampini 
1757c9ed8603SStefano Zampini     if (pcbddc->benign_p0_lidx >= 0) benign = 1;
1758a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1759a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
17600fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1761a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1762a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
1763019a44ceSStefano 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);
1764a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1765a64d13efSStefano Zampini   }
1766a64d13efSStefano Zampini 
1767a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
17686816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
17696816873aSStefano Zampini     IS       is_aux1,is_aux2;
17706816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
17716816873aSStefano Zampini 
17723a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1773854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
1774854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
1775a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
17764641a718SStefano Zampini     for (i=0; i<n_D; i++) {
17774641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
17784641a718SStefano Zampini     }
1779a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1780a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
17814641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
17824641a718SStefano Zampini         aux_array1[j++] = i;
1783a64d13efSStefano Zampini       }
1784a64d13efSStefano Zampini     }
1785a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1786a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1787a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
17884641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
17894641a718SStefano Zampini         aux_array2[j++] = i;
1790a64d13efSStefano Zampini       }
1791a64d13efSStefano Zampini     }
1792a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1793a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
1794a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1795a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1796a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1797a64d13efSStefano Zampini 
17988eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
1799785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
1800a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
18014641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
18024641a718SStefano Zampini           aux_array1[j++] = i;
1803a64d13efSStefano Zampini         }
1804a64d13efSStefano Zampini       }
1805a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1806a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1807a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1808a64d13efSStefano Zampini     }
18094641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
18103a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1811d62866d3SStefano Zampini   } else {
181253892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
18136816873aSStefano Zampini     IS               tis;
18146816873aSStefano Zampini     PetscInt         schur_size;
18156816873aSStefano Zampini 
181653892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
18176816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
181853892102SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
18196816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
18206816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
18216816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
18226816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
18236816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
1824d62866d3SStefano Zampini     }
1825d62866d3SStefano Zampini   }
1826a64d13efSStefano Zampini   PetscFunctionReturn(0);
1827a64d13efSStefano Zampini }
1828a64d13efSStefano Zampini 
1829304d26faSStefano Zampini 
1830304d26faSStefano Zampini #undef __FUNCT__
1831304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1832684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1833304d26faSStefano Zampini {
1834304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1835304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1836304d26faSStefano Zampini   PC             pc_temp;
1837304d26faSStefano Zampini   Mat            A_RR;
1838f4ddd8eeSStefano Zampini   MatReuse       reuse;
1839304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1840304d26faSStefano Zampini   PetscReal      value;
184104708bb6SStefano Zampini   PetscInt       n_D,n_R;
18429577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1843304d26faSStefano Zampini   PetscErrorCode ierr;
1844e604994aSStefano Zampini   /* prefixes stuff */
1845312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1846e604994aSStefano Zampini   size_t         len;
1847304d26faSStefano Zampini 
1848304d26faSStefano Zampini   PetscFunctionBegin;
1849304d26faSStefano Zampini 
1850e604994aSStefano Zampini   /* compute prefixes */
1851e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1852e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1853e604994aSStefano Zampini   if (!pcbddc->current_level) {
1854e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1855e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1856e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1857e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1858e604994aSStefano Zampini   } else {
1859e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1860312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1861e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1862e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1863312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1864312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
186534d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
186634d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1867e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1868e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1869e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1870e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1871e604994aSStefano Zampini   }
1872e604994aSStefano Zampini 
1873304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1874684f6988SStefano Zampini   if (dirichlet) {
1875d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
18763301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
18773301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
1878964fefecSStefano Zampini     }
1879ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
1880964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
1881304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1882304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1883304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1884304d26faSStefano Zampini       /* default */
1885304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1886e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
18879577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1888304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
18899577ea80SStefano Zampini       if (issbaij) {
18909577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
18919577ea80SStefano Zampini       } else {
1892304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
18939577ea80SStefano Zampini       }
1894304d26faSStefano Zampini       /* Allow user's customization */
1895304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1896304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1897304d26faSStefano Zampini     }
1898d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1899d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
1900d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1901d62866d3SStefano Zampini 
1902d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
1903d5574798SStefano Zampini     }
1904304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1905304d26faSStefano Zampini     if (!n_D) {
1906304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1907304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1908304d26faSStefano Zampini     }
1909304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1910304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1911304d26faSStefano Zampini     /* set ksp_D into pcis data */
1912304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1913304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1914304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1915684f6988SStefano Zampini   }
1916304d26faSStefano Zampini 
1917304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1918684f6988SStefano Zampini   A_RR = 0;
1919684f6988SStefano Zampini   if (neumann) {
1920d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
192104708bb6SStefano Zampini     PetscInt        ibs,mbs;
192204708bb6SStefano Zampini     PetscBool       issbaij;
192304708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
1924f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
19258ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1926f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1927f4ddd8eeSStefano Zampini       PetscInt nn_R;
192881d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1929f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1930f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1931f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1932f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1933f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1934f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1935f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1936727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1937f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1938f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1939f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1940f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1941f4ddd8eeSStefano Zampini         }
1942f4ddd8eeSStefano Zampini       }
1943f4ddd8eeSStefano Zampini       /* last check */
1944d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1945f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1946f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1947f4ddd8eeSStefano Zampini       }
1948f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1949f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1950f4ddd8eeSStefano Zampini     }
1951f4ddd8eeSStefano Zampini     /* extract A_RR */
1952af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1953af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
195404708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
195504708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
195604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
195704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
195804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
1959af732b37SStefano Zampini       } else {
196004708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
19616816873aSStefano Zampini       }
196204708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
196304708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
196404708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
196504708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
196604708bb6SStefano Zampini       } else {
196704708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
196804708bb6SStefano Zampini       }
196904708bb6SStefano Zampini     }
197004708bb6SStefano Zampini     if (!sub_schurs->reuse_mumps) {
1971f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
19723301b35fSStefano Zampini       if (pcbddc->local_mat->symmetric_set) {
19733301b35fSStefano Zampini         ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
19746816873aSStefano Zampini       }
19756816873aSStefano Zampini     } else {
19766816873aSStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
19776816873aSStefano Zampini 
19786816873aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
19796816873aSStefano Zampini       ierr = PCGetOperators(reuse_mumps->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
19806816873aSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1981af732b37SStefano Zampini     }
1982f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
1983304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1984304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1985304d26faSStefano Zampini       /* default */
1986304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1987e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
1988304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
19899577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
19909577ea80SStefano Zampini       if (issbaij) {
19919577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
19929577ea80SStefano Zampini       } else {
1993304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
19949577ea80SStefano Zampini       }
1995304d26faSStefano Zampini       /* Allow user's customization */
1996304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1997304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1998304d26faSStefano Zampini     }
1999d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2000304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2001304d26faSStefano Zampini     if (!n_R) {
2002304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2003304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2004304d26faSStefano Zampini     }
2005d62866d3SStefano Zampini     /* Reuse MUMPS solver if it is present */
2006d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2007d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2008d62866d3SStefano Zampini 
2009d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
2010d62866d3SStefano Zampini     }
2011304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
2012304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2013684f6988SStefano Zampini   }
20146816873aSStefano Zampini   /* free Neumann problem's matrix */
20156816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2016304d26faSStefano Zampini 
2017304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
20180fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2019684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
2020684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2021684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2022684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2023684f6988SStefano Zampini     }
2024684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
20250fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
20260fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
20270fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
20280fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
20290fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2030304d26faSStefano Zampini       /* need to be adapted? */
2031b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2032b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2033b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2034304d26faSStefano Zampini       /* print info */
2035304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2036e604994aSStefano 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);
2037304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2038304d26faSStefano Zampini       }
2039b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2040298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2041304d26faSStefano Zampini       }
2042684f6988SStefano Zampini     }
2043684f6988SStefano Zampini     if (neumann) { /* Neumann */
20446816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
20450fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
20460fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
20470fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
20480fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
20490fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2050304d26faSStefano Zampini       /* need to be adapted? */
2051b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2052b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2053304d26faSStefano Zampini       /* print info */
2054304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2055e604994aSStefano 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);
2056304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2057304d26faSStefano Zampini       }
2058b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2059298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2060304d26faSStefano Zampini       }
20610fccc4e9SStefano Zampini     }
2062684f6988SStefano Zampini   }
2063304d26faSStefano Zampini   PetscFunctionReturn(0);
2064304d26faSStefano Zampini }
2065304d26faSStefano Zampini 
2066304d26faSStefano Zampini #undef __FUNCT__
2067ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
206880677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2069674ae819SStefano Zampini {
2070674ae819SStefano Zampini   PetscErrorCode  ierr;
2071674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2072be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2073674ae819SStefano Zampini 
2074674ae819SStefano Zampini   PetscFunctionBegin;
2075be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
207680677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
207720c7b377SStefano Zampini   }
207880677318SStefano Zampini   if (!pcbddc->switch_static) {
207980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
208080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
208180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
208220c7b377SStefano Zampini     }
2083be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
208480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
208580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
208620c7b377SStefano Zampini     } else {
2087be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2088be83ff47SStefano Zampini 
208953892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
209053892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
209120c7b377SStefano Zampini     }
2092be83ff47SStefano Zampini   } else {
209380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
209480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
209580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
209680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
209780677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
209880677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
209980677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
210080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
210180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2102674ae819SStefano Zampini     }
2103674ae819SStefano Zampini   }
2104be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
210580677318SStefano Zampini     if (applytranspose) {
210680677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
210780677318SStefano Zampini     } else {
210880677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
210980677318SStefano Zampini     }
211053892102SStefano Zampini #if defined(PETSC_HAVE_MUMPS)
2111be83ff47SStefano Zampini   } else {
2112be83ff47SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2113be83ff47SStefano Zampini 
2114be83ff47SStefano Zampini     if (applytranspose) {
211553892102SStefano Zampini       ierr = MatMumpsSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2116be83ff47SStefano Zampini     } else {
211753892102SStefano Zampini       ierr = MatMumpsSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2118be83ff47SStefano Zampini     }
211953892102SStefano Zampini #endif
2120be83ff47SStefano Zampini   }
212180677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
212280677318SStefano Zampini   if (!pcbddc->switch_static) {
2123be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
212480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
212580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2126be83ff47SStefano Zampini     } else {
2127be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2128be83ff47SStefano Zampini 
212953892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213053892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2131be83ff47SStefano Zampini     }
213280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
213380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
213480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
213580677318SStefano Zampini     }
213680677318SStefano Zampini   } else {
213780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214180677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
214280677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
214380677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
214480677318SStefano Zampini     }
214580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2149674ae819SStefano Zampini   }
2150674ae819SStefano Zampini   PetscFunctionReturn(0);
2151674ae819SStefano Zampini }
2152674ae819SStefano Zampini 
2153dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2154674ae819SStefano Zampini #undef __FUNCT__
2155674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2156dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2157674ae819SStefano Zampini {
2158674ae819SStefano Zampini   PetscErrorCode ierr;
2159674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2160674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2161674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2162674ae819SStefano Zampini 
2163674ae819SStefano Zampini   PetscFunctionBegin;
2164dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2165dc359a40SStefano Zampini   if (applytranspose) {
2166674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
21678eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2168dc359a40SStefano Zampini   } else {
2169674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2170674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
217115aaf578SStefano Zampini   }
2172efc2fbd9SStefano Zampini 
2173efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
2174c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
2175efc2fbd9SStefano Zampini     PetscScalar *array;
2176efc2fbd9SStefano Zampini 
2177efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2178efc2fbd9SStefano Zampini     array[pcbddc->local_primal_size-1] += pcbddc->benign_p0;
2179efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2180efc2fbd9SStefano Zampini   }
2181efc2fbd9SStefano Zampini 
218212edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
218312edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
218412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218612edc857SStefano Zampini 
21879f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
218812edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
218912edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
2190964fefecSStefano Zampini     Vec rhs,sol;
2191964fefecSStefano Zampini 
2192964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2193964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
219412edc857SStefano Zampini     if (applytranspose) {
2195964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
219612edc857SStefano Zampini     } else {
2197964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
219812edc857SStefano Zampini     }
219912edc857SStefano Zampini   }
2200674ae819SStefano Zampini 
2201674ae819SStefano Zampini   /* Local solution on R nodes */
220280677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
220380677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
22049f00e9b4SStefano Zampini   }
2205674ae819SStefano Zampini 
22069f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
22079f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
220812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2209674ae819SStefano Zampini 
2210674ae819SStefano Zampini   /* Sum contributions from two levels */
2211dc359a40SStefano Zampini   if (applytranspose) {
2212dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2213dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2214dc359a40SStefano Zampini   } else {
2215674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
22168eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2217dc359a40SStefano Zampini   }
2218efc2fbd9SStefano Zampini   /* store p0 */
2219c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
2220efc2fbd9SStefano Zampini     PetscScalar *array;
2221efc2fbd9SStefano Zampini 
2222efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2223efc2fbd9SStefano Zampini     pcbddc->benign_p0 = array[pcbddc->local_primal_size-1];
2224efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2225efc2fbd9SStefano Zampini   }
2226674ae819SStefano Zampini   PetscFunctionReturn(0);
2227674ae819SStefano Zampini }
2228674ae819SStefano Zampini 
2229674ae819SStefano Zampini #undef __FUNCT__
2230674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
223112edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2232674ae819SStefano Zampini {
2233674ae819SStefano Zampini   PetscErrorCode ierr;
2234674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
223558da7f69SStefano Zampini   PetscScalar    *array;
223612edc857SStefano Zampini   Vec            from,to;
2237674ae819SStefano Zampini 
2238674ae819SStefano Zampini   PetscFunctionBegin;
223912edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
224012edc857SStefano Zampini     from = pcbddc->coarse_vec;
224112edc857SStefano Zampini     to = pcbddc->vec1_P;
224212edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
224312edc857SStefano Zampini       Vec tvec;
224458da7f69SStefano Zampini 
224558da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
224658da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
224712edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
224858da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
224958da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
225058da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
225112edc857SStefano Zampini     }
225212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
225312edc857SStefano Zampini     from = pcbddc->vec1_P;
225412edc857SStefano Zampini     to = pcbddc->coarse_vec;
225512edc857SStefano Zampini   }
225612edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2257674ae819SStefano Zampini   PetscFunctionReturn(0);
2258674ae819SStefano Zampini }
2259674ae819SStefano Zampini 
2260674ae819SStefano Zampini #undef __FUNCT__
2261674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
226212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
2263674ae819SStefano Zampini {
2264674ae819SStefano Zampini   PetscErrorCode ierr;
2265674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
226658da7f69SStefano Zampini   PetscScalar    *array;
226712edc857SStefano Zampini   Vec            from,to;
2268674ae819SStefano Zampini 
2269674ae819SStefano Zampini   PetscFunctionBegin;
227012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
227112edc857SStefano Zampini     from = pcbddc->coarse_vec;
227212edc857SStefano Zampini     to = pcbddc->vec1_P;
227312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
227412edc857SStefano Zampini     from = pcbddc->vec1_P;
227512edc857SStefano Zampini     to = pcbddc->coarse_vec;
227612edc857SStefano Zampini   }
227712edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
227812edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
227912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
228012edc857SStefano Zampini       Vec tvec;
228158da7f69SStefano Zampini 
228212edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
228358da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
228458da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
228558da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
228658da7f69SStefano Zampini     }
228758da7f69SStefano Zampini   } else {
228858da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
228958da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
229012edc857SStefano Zampini     }
229112edc857SStefano Zampini   }
2292674ae819SStefano Zampini   PetscFunctionReturn(0);
2293674ae819SStefano Zampini }
2294674ae819SStefano Zampini 
2295984c4197SStefano Zampini /* uncomment for testing purposes */
2296984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
2297674ae819SStefano Zampini #undef __FUNCT__
2298674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
2299674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
2300674ae819SStefano Zampini {
2301674ae819SStefano Zampini   PetscErrorCode    ierr;
2302674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
2303674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
2304674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
2305984c4197SStefano Zampini   /* one and zero */
2306984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
2307984c4197SStefano Zampini   /* space to store constraints and their local indices */
23089162d606SStefano Zampini   PetscScalar       *constraints_data;
23099162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
23109162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
23119162d606SStefano Zampini   PetscInt          *constraints_n;
2312984c4197SStefano Zampini   /* iterators */
2313b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
2314984c4197SStefano Zampini   /* BLAS integers */
2315e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
2316e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2317c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2318727cdba6SStefano Zampini   /* reuse */
23190e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
23200e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2321984c4197SStefano Zampini   /* change of basis */
2322b3d85658SStefano Zampini   PetscBool         qr_needed;
23239162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
2324984c4197SStefano Zampini   /* auxiliary stuff */
232564efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
23268a0068c3SStefano Zampini   PetscInt          ncc;
2327984c4197SStefano Zampini   /* some quantities */
232845a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2329a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2330984c4197SStefano Zampini 
2331674ae819SStefano Zampini   PetscFunctionBegin;
23328e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
23338e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
23348e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2335088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
2336088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
23370e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
23380e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
23390e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
23400e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
23410e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2342088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2343cf5a6209SStefano Zampini 
2344cf5a6209SStefano Zampini   /* print some info */
2345cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
2346cf5a6209SStefano Zampini     IS       vertices;
2347cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
2348cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2349cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2350cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2351cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2352cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2353cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2354fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2355fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2356cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2357cf5a6209SStefano Zampini   }
2358cf5a6209SStefano Zampini 
2359cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
23609162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
2361cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
2362cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
2363cf5a6209SStefano Zampini     Vec          *localnearnullsp;
2364cf5a6209SStefano Zampini     PetscScalar  *array;
2365cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2366cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
2367674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
2368b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
2369674ae819SStefano Zampini     PetscScalar  *work;
2370674ae819SStefano Zampini     PetscReal    *singular_vals;
2371674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2372674ae819SStefano Zampini     PetscReal    *rwork;
2373674ae819SStefano Zampini #endif
2374674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2375674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
2376674ae819SStefano Zampini #else
2377964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
2378964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
2379674ae819SStefano Zampini #endif
2380674ae819SStefano Zampini 
2381674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
2382d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2383d06fc5fdSStefano Zampini     /* free unneeded index sets */
2384d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
2385d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2386674ae819SStefano Zampini     }
2387d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
2388d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
2389d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2390d06fc5fdSStefano Zampini       }
2391d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2392d06fc5fdSStefano Zampini       n_ISForEdges = 0;
2393d06fc5fdSStefano Zampini     }
2394d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
2395d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
2396d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2397d06fc5fdSStefano Zampini       }
2398d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2399d06fc5fdSStefano Zampini       n_ISForFaces = 0;
2400d06fc5fdSStefano Zampini     }
240170022509SStefano Zampini 
240270022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
240370022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
240470022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
240570022509SStefano Zampini     if (pcbddc->NullSpace) {
240670022509SStefano Zampini       PetscBool tbool[2],gbool[2];
240770022509SStefano Zampini 
240870022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2409b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
2410d06fc5fdSStefano Zampini         if (!ISForEdges) {
2411d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
2412d06fc5fdSStefano Zampini         }
2413b8ffe317SStefano Zampini       }
2414d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
2415d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
2416d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2417d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
2418d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
241998a51de6SStefano Zampini     }
242070022509SStefano Zampini #endif
242108122e43SStefano Zampini 
2422674ae819SStefano Zampini     /* check if near null space is attached to global mat */
2423674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2424674ae819SStefano Zampini     if (nearnullsp) {
2425674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2426f4ddd8eeSStefano Zampini       /* remove any stored info */
2427f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2428f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2429f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
2430f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2431f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
2432473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2433f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
2434f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2435f4ddd8eeSStefano Zampini       }
2436984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
2437984c4197SStefano Zampini       nnsp_size = 0;
2438674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
2439674ae819SStefano Zampini     }
2440984c4197SStefano Zampini     /* get max number of constraints on a single cc */
2441984c4197SStefano Zampini     max_constraints = nnsp_size;
2442984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
2443984c4197SStefano Zampini 
2444674ae819SStefano Zampini     /*
2445674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
24469162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
24479162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
24489162d606SStefano Zampini          There can be multiple constraints per connected component
2449674ae819SStefano Zampini                                                                                                                                                            */
2450674ae819SStefano Zampini     n_vertices = 0;
2451674ae819SStefano Zampini     if (ISForVertices) {
2452674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2453674ae819SStefano Zampini     }
24549162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
24559162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
24569162d606SStefano Zampini 
24579162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
24589162d606SStefano Zampini     total_counts *= max_constraints;
2459674ae819SStefano Zampini     total_counts += n_vertices;
24604641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
24619162d606SStefano Zampini 
2462674ae819SStefano Zampini     total_counts = 0;
2463674ae819SStefano Zampini     max_size_of_constraint = 0;
2464674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
24659162d606SStefano Zampini       IS used_is;
2466674ae819SStefano Zampini       if (i<n_ISForEdges) {
24679162d606SStefano Zampini         used_is = ISForEdges[i];
2468674ae819SStefano Zampini       } else {
24699162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
2470674ae819SStefano Zampini       }
24719162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2472674ae819SStefano Zampini       total_counts += j;
2473674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2474674ae819SStefano Zampini     }
24759162d606SStefano 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);
24769162d606SStefano Zampini 
2477984c4197SStefano Zampini     /* get local part of global near null space vectors */
2478785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2479984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2480984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2481e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2482e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2483984c4197SStefano Zampini     }
2484674ae819SStefano Zampini 
2485242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
2486242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
2487a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2488242a89d7SStefano Zampini 
2489984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2490a773dcb8SStefano Zampini     if (!skip_lapack) {
2491674ae819SStefano Zampini       PetscScalar temp_work;
2492911cabfeSStefano Zampini 
2493674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2494984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2495785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2496785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2497785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2498674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2499785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2500674ae819SStefano Zampini #endif
2501674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2502c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2503c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2504674ae819SStefano Zampini       lwork = -1;
2505674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2506674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2507c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2508674ae819SStefano Zampini #else
2509c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2510674ae819SStefano Zampini #endif
2511674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2512984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2513674ae819SStefano Zampini #else /* on missing GESVD */
2514674ae819SStefano Zampini       /* SVD */
2515674ae819SStefano Zampini       PetscInt max_n,min_n;
2516674ae819SStefano Zampini       max_n = max_size_of_constraint;
2517984c4197SStefano Zampini       min_n = max_constraints;
2518984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
2519674ae819SStefano Zampini         min_n = max_size_of_constraint;
2520984c4197SStefano Zampini         max_n = max_constraints;
2521674ae819SStefano Zampini       }
2522785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2523674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2524785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2525674ae819SStefano Zampini #endif
2526674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2527674ae819SStefano Zampini       lwork = -1;
2528e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2529e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2530b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2531674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2532674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
25339162d606SStefano 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));
2534674ae819SStefano Zampini #else
25359162d606SStefano 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));
2536674ae819SStefano Zampini #endif
2537674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2538984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2539984c4197SStefano Zampini #endif /* on missing GESVD */
2540674ae819SStefano Zampini       /* Allocate optimal workspace */
2541674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2542854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2543674ae819SStefano Zampini     }
2544674ae819SStefano Zampini     /* Now we can loop on constraining sets */
2545674ae819SStefano Zampini     total_counts = 0;
25469162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
25479162d606SStefano Zampini     constraints_data_ptr[0] = 0;
2548674ae819SStefano Zampini     /* vertices */
25499162d606SStefano Zampini     if (n_vertices) {
2550674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
25519162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2552674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
25539162d606SStefano Zampini         constraints_n[total_counts] = 1;
25549162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
25559162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
25569162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2557674ae819SStefano Zampini         total_counts++;
2558674ae819SStefano Zampini       }
2559674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2560674ae819SStefano Zampini       n_vertices = total_counts;
2561674ae819SStefano Zampini     }
2562984c4197SStefano Zampini 
2563674ae819SStefano Zampini     /* edges and faces */
25649162d606SStefano Zampini     total_counts_cc = total_counts;
2565911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
25669162d606SStefano Zampini       IS        used_is;
25679162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
25689162d606SStefano Zampini 
2569911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
25709162d606SStefano Zampini         used_is = ISForEdges[ncc];
2571984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2572674ae819SStefano Zampini       } else {
25739162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
2574984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2575674ae819SStefano Zampini       }
2576674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
25779162d606SStefano Zampini 
25789162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
25799162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2580984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
2581984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2582674ae819SStefano Zampini       if (nnsp_has_cnst) {
25835b08dc53SStefano Zampini         PetscScalar quad_value;
25849162d606SStefano Zampini 
25859162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
25869162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
25879162d606SStefano Zampini 
2588a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
2589674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2590a773dcb8SStefano Zampini         } else {
2591a773dcb8SStefano Zampini           quad_value = 1.0;
2592a773dcb8SStefano Zampini         }
2593674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
25949162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
2595674ae819SStefano Zampini         }
25969162d606SStefano Zampini         temp_constraints++;
2597674ae819SStefano Zampini         total_counts++;
2598674ae819SStefano Zampini       }
2599674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
2600984c4197SStefano Zampini         PetscReal real_value;
26019162d606SStefano Zampini         PetscScalar *ptr_to_data;
26029162d606SStefano Zampini 
2603984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
26049162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
2605674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
26069162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
2607674ae819SStefano Zampini         }
2608984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2609984c4197SStefano Zampini         /* check if array is null on the connected component */
2610e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
26119162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
26125b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2613674ae819SStefano Zampini           temp_constraints++;
2614674ae819SStefano Zampini           total_counts++;
26159162d606SStefano Zampini           if (!idxs_copied) {
26169162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
26179162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
2618674ae819SStefano Zampini           }
2619674ae819SStefano Zampini         }
26209162d606SStefano Zampini       }
26219162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
262245a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2623eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2624a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
26259162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
26269162d606SStefano Zampini 
26279162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2628a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
26299162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
2630a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
26319162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
2632a773dcb8SStefano Zampini         } else { /* perform SVD */
2633984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
26349162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2635674ae819SStefano Zampini 
2636674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2637984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
2638984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
2639984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
2640984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
2641984c4197SStefano Zampini                 from that computed using LAPACKgesvd
2642984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
2643984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
2644984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
2645674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
2646e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2647984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2648674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
2649674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
26509162d606SStefano 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));
2651674ae819SStefano Zampini             }
2652674ae819SStefano Zampini           }
2653e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
2654e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2655e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
2656674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2657c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
2658674ae819SStefano Zampini #else
2659c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
2660674ae819SStefano Zampini #endif
2661674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2662984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
2663984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
2664674ae819SStefano Zampini           j = 0;
2665984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
2666674ae819SStefano Zampini           total_counts = total_counts-j;
266745a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
2668e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
2669c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2670c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2671c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
2672c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2673c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
2674c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2675674ae819SStefano Zampini           if (j<temp_constraints) {
2676984c4197SStefano Zampini             PetscInt ii;
2677984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
2678674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
26799162d606SStefano 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));
2680674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2681984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
2682674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
26839162d606SStefano 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];
2684674ae819SStefano Zampini               }
2685674ae819SStefano Zampini             }
2686674ae819SStefano Zampini           }
2687674ae819SStefano Zampini #else  /* on missing GESVD */
2688e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
2689e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
2690b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2691674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2692674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
26939162d606SStefano 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));
2694674ae819SStefano Zampini #else
26959162d606SStefano 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));
2696674ae819SStefano Zampini #endif
2697984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
2698674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2699984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
2700e310c8b4SStefano Zampini           k = temp_constraints;
2701e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
2702674ae819SStefano Zampini           j = 0;
2703e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
270445a1bb75SStefano Zampini           valid_constraints = k-j;
2705911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
2706984c4197SStefano Zampini #endif /* on missing GESVD */
2707674ae819SStefano Zampini         }
2708a773dcb8SStefano Zampini       }
27099162d606SStefano Zampini       /* update pointers information */
27109162d606SStefano Zampini       if (valid_constraints) {
27119162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
27129162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
27139162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
27149162d606SStefano Zampini         /* set change_of_basis flag */
271545a1bb75SStefano Zampini         if (boolforchange) {
2716b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
27179162d606SStefano Zampini         }
2718b3d85658SStefano Zampini         total_counts_cc++;
271945a1bb75SStefano Zampini       }
272045a1bb75SStefano Zampini     }
2721984c4197SStefano Zampini     /* free workspace */
27228f1c130eSStefano Zampini     if (!skip_lapack) {
2723984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
2724984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2725984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
2726984c4197SStefano Zampini #endif
2727984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
2728984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2729984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
2730984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2731984c4197SStefano Zampini #endif
2732984c4197SStefano Zampini     }
2733984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2734984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
2735984c4197SStefano Zampini     }
2736984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
2737cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
2738cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
2739cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2740cf5a6209SStefano Zampini     }
2741cf5a6209SStefano Zampini     if (n_ISForFaces) {
2742cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2743cf5a6209SStefano Zampini     }
2744cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
2745cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2746cf5a6209SStefano Zampini     }
2747cf5a6209SStefano Zampini     if (n_ISForEdges) {
2748cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2749cf5a6209SStefano Zampini     }
2750cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
275108122e43SStefano Zampini   } else {
275208122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2753984c4197SStefano Zampini 
275408122e43SStefano Zampini     total_counts = 0;
275508122e43SStefano Zampini     n_vertices = 0;
2756d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
2757d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
275808122e43SStefano Zampini     }
275908122e43SStefano Zampini     max_constraints = 0;
27609162d606SStefano Zampini     total_counts_cc = 0;
276108122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
276208122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
27639162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
276408122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
276508122e43SStefano Zampini     }
27669162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
27679162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
27689162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
27699162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
277074d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
27719162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
27729162d606SStefano Zampini     total_counts_cc = 0;
27739162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
27749162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
27759162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
277608122e43SStefano Zampini       }
277708122e43SStefano Zampini     }
27789162d606SStefano Zampini #if 0
27799162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
27809162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
27819162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
27829162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
27839162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
27849162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
27859162d606SStefano Zampini       }
27869162d606SStefano Zampini       printf("\n");
27879162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
27889162d606SStefano Zampini     }
27891b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
27908bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
27911b968477SStefano Zampini     }
27921b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
27938bec7fa6SStefano 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]);
27941b968477SStefano Zampini     }
279508122e43SStefano Zampini #endif
279608122e43SStefano Zampini 
27978bec7fa6SStefano Zampini     max_size_of_constraint = 0;
27989162d606SStefano 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]);
27999162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
280008122e43SStefano Zampini     /* Change of basis */
2801b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
280208122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
280308122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
280408122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
2805b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
280608122e43SStefano Zampini         }
280708122e43SStefano Zampini       }
280808122e43SStefano Zampini     }
280908122e43SStefano Zampini   }
2810984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
2811019a44ceSStefano Zampini   /* allocating one extra space (in case an extra primal dof should be stored for the benign trick */
2812019a44ceSStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+1,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
281308122e43SStefano Zampini 
28149162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
28159162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
28169162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
28179162d606SStefano 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);
281808122e43SStefano Zampini   }
2819674ae819SStefano Zampini 
2820674ae819SStefano Zampini   /* Create constraint matrix */
2821674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
282216f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
2823984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
2824984c4197SStefano Zampini 
2825984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
2826a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
2827a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
282874d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
2829984c4197SStefano Zampini   total_primal_vertices=0;
2830b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
28319162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
28329162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2833984c4197SStefano Zampini     if (size_of_constraint == 1) {
28349162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
2835b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
283664efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
28379162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
28389162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
2839a717540cSStefano Zampini       }
2840b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
284174d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
2842a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
2843a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
2844a717540cSStefano Zampini       }
2845fa434743SStefano Zampini     } else {
2846b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
2847fa434743SStefano Zampini     }
2848a717540cSStefano Zampini   }
2849b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
2850b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
2851674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
285270022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2853b3d85658SStefano Zampini 
2854019a44ceSStefano Zampini   /* allocating one extra space (in case an extra primal dof should be stored for the benign trick */
2855019a44ceSStefano 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);
28560e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
28570e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
2858984c4197SStefano Zampini 
2859984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
286074d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
2861785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2862984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
286374d5cdf7SStefano Zampini 
2864984c4197SStefano Zampini   j = total_primal_vertices;
286574d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
2866b3d85658SStefano Zampini   cum = total_primal_vertices;
28679162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
28684641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2869b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
2870b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
2871b3d85658SStefano Zampini       cum++;
28729162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
287374d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
287474d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
287574d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
287674d5cdf7SStefano Zampini       }
28779162d606SStefano Zampini       j += constraints_n[i];
2878674ae819SStefano Zampini     }
2879674ae819SStefano Zampini   }
2880674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2881674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2882088faed8SStefano Zampini 
2883674ae819SStefano Zampini   /* set values in constraint matrix */
2884984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
28850e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2886674ae819SStefano Zampini   }
2887984c4197SStefano Zampini   total_counts = total_primal_vertices;
28889162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
28894641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
28909162d606SStefano Zampini       PetscInt *cols;
28919162d606SStefano Zampini 
28929162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
28939162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
28949162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
28959162d606SStefano Zampini         PetscInt    row = total_counts+k;
28969162d606SStefano Zampini         PetscScalar *vals;
28979162d606SStefano Zampini 
28989162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
28999162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
29009162d606SStefano Zampini       }
29019162d606SStefano Zampini       total_counts += constraints_n[i];
2902674ae819SStefano Zampini     }
2903674ae819SStefano Zampini   }
2904674ae819SStefano Zampini   /* assembling */
2905674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2906674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2907088faed8SStefano Zampini 
2908984c4197SStefano Zampini   /*
290945a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2910984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2911984c4197SStefano Zampini   */
2912674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2913674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2914026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2915984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2916984c4197SStefano Zampini     /* working stuff for GEQRF */
291781d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2918984c4197SStefano Zampini     PetscBLASInt lqr_work;
2919984c4197SStefano Zampini     /* working stuff for UNGQR */
2920984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2921984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2922984c4197SStefano Zampini     /* working stuff for TRTRS */
2923984c4197SStefano Zampini     PetscScalar  *trs_rhs;
29243f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2925984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2926984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2927984c4197SStefano Zampini     PetscScalar  *start_vals;
2928984c4197SStefano Zampini     /* working stuff for values insertion */
29294641a718SStefano Zampini     PetscBT      is_primal;
293064efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
2931906d46d4SStefano Zampini     /* matrix sizes */
2932906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2933906d46d4SStefano Zampini     /* temporary change of basis */
2934906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2935cf5a6209SStefano Zampini     /* extra space for debugging */
2936cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
2937984c4197SStefano Zampini 
2938906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2939906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
294016f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2941bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
2942906d46d4SStefano Zampini     /* nonzeros for local mat */
2943bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
2944bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
29459162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
2946a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
29479162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
2948a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
29499162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
2950a717540cSStefano Zampini         } else {
29519162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
29529162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
2953a717540cSStefano Zampini         }
2954a717540cSStefano Zampini       }
2955a717540cSStefano Zampini     }
2956906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2957bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2958a717540cSStefano Zampini     /* Set initial identity in the matrix */
2959bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
2960906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2961a717540cSStefano Zampini     }
2962a717540cSStefano Zampini 
2963a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2964a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2965a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2966a717540cSStefano Zampini     }
2967a717540cSStefano Zampini 
2968a717540cSStefano Zampini 
2969a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2970a717540cSStefano Zampini     /*
2971a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2972a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2973a717540cSStefano Zampini 
2974a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2975a717540cSStefano Zampini 
2976a6b551f4SStefano 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)
2977a6b551f4SStefano Zampini 
2978a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2979a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2980a717540cSStefano Zampini             |              ...                        |
2981a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2982a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2983a717540cSStefano Zampini 
2984a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2985a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2986a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2987a6b551f4SStefano Zampini 
2988a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2989a717540cSStefano Zampini     */
2990a717540cSStefano Zampini     if (qr_needed) {
2991984c4197SStefano Zampini       /* space to store Q */
2992854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2993984c4197SStefano Zampini       /* first we issue queries for optimal work */
29943f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
29953f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
29963f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2997984c4197SStefano Zampini       lqr_work = -1;
29983f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2999984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3000984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3001785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3002984c4197SStefano Zampini       lgqr_work = -1;
30033f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
30043f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
30053f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
30063f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
30073f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
30083f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3009984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3010984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3011785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3012984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3013785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3014984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3015785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3016a717540cSStefano Zampini       /* allocating workspace for check */
3017a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3018cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3019a717540cSStefano Zampini       }
3020a717540cSStefano Zampini     }
3021984c4197SStefano Zampini     /* array to store whether a node is primal or not */
30224641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3023473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
30240e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
302539e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
302639e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
30274641a718SStefano Zampini     }
302839e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
302939e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
303039e2fb2aSStefano Zampini     }
303139e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3032984c4197SStefano Zampini 
3033a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
30349162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
30359162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
30364641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3037984c4197SStefano Zampini         /* get constraint info */
30389162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3039984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3040984c4197SStefano Zampini 
3041984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
30429162d606SStefano 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);
3043674ae819SStefano Zampini         }
3044984c4197SStefano Zampini 
3045fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3046a717540cSStefano Zampini 
3047a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3048a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
30499162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3050a717540cSStefano Zampini           }
3051984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
30529162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3053984c4197SStefano Zampini 
3054984c4197SStefano Zampini           /* compute QR decomposition of constraints */
30553f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
30563f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
30573f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3058674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30593f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3060984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3061674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3062984c4197SStefano Zampini 
3063984c4197SStefano Zampini           /* explictly compute R^-T */
3064984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3065984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
30663f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
30673f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
30683f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
30693f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3070984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30713f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3072984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3073984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3074984c4197SStefano Zampini 
3075a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
30763f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
30773f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
30783f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
30793f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3080984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30813f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3082984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3083984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3084984c4197SStefano Zampini 
3085984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3086984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3087984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
30883f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
30893f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
30903f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
30913f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
30923f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
30933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3094984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30959162d606SStefano 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));
3096984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
30979162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3098984c4197SStefano Zampini 
3099984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
31009162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3101984c4197SStefano Zampini           /* insert cols for primal dofs */
3102984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3103984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
31049162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3105906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3106984c4197SStefano Zampini           }
3107984c4197SStefano Zampini           /* insert cols for dual dofs */
3108984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
31099162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3110984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
31119162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3112906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3113984c4197SStefano Zampini               j++;
3114674ae819SStefano Zampini             }
3115674ae819SStefano Zampini           }
3116984c4197SStefano Zampini 
3117984c4197SStefano Zampini           /* check change of basis */
3118984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3119984c4197SStefano Zampini             PetscInt   ii,jj;
3120984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3121c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3122c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3123c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3124c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3125c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3126c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3127984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3128cf5a6209SStefano 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));
3129984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3130984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3131984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3132cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3133cf5a6209SStefano 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;
3134674ae819SStefano Zampini               }
3135674ae819SStefano Zampini             }
3136984c4197SStefano Zampini             if (!valid_qr) {
313722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3138984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3139984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3140cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3141cf5a6209SStefano 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]));
3142674ae819SStefano Zampini                   }
3143cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3144cf5a6209SStefano 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]));
3145984c4197SStefano Zampini                   }
3146984c4197SStefano Zampini                 }
3147984c4197SStefano Zampini               }
3148674ae819SStefano Zampini             } else {
314922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3150674ae819SStefano Zampini             }
3151674ae819SStefano Zampini           }
3152a717540cSStefano Zampini         } else { /* simple transformation block */
3153a717540cSStefano Zampini           PetscInt    row,col;
3154a6b551f4SStefano Zampini           PetscScalar val,norm;
3155a6b551f4SStefano Zampini 
3156a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
31579162d606SStefano 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));
3158a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
31599162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
31609162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3161bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
31629162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3163906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
31649162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3165a717540cSStefano Zampini             } else {
3166a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
31679162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3168a717540cSStefano Zampini                 if (row != col) {
31699162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3170a717540cSStefano Zampini                 } else {
31719162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3172a717540cSStefano Zampini                 }
3173906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3174a717540cSStefano Zampini               }
3175a717540cSStefano Zampini             }
3176a717540cSStefano Zampini           }
317798a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
317822d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3179a717540cSStefano Zampini           }
3180674ae819SStefano Zampini         }
3181984c4197SStefano Zampini       } else {
3182984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
31839162d606SStefano 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);
3184674ae819SStefano Zampini         }
3185674ae819SStefano Zampini       }
3186674ae819SStefano Zampini     }
3187a717540cSStefano Zampini 
3188a717540cSStefano Zampini     /* free workspace */
3189a717540cSStefano Zampini     if (qr_needed) {
3190984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
3191cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3192984c4197SStefano Zampini       }
3193984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3194984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3195984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3196984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3197984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3198674ae819SStefano Zampini     }
3199a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3200906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3201906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3202906d46d4SStefano Zampini 
3203906d46d4SStefano Zampini     /* assembling of global change of variable */
3204bbb9e6c6SStefano Zampini     {
3205bbb9e6c6SStefano Zampini       Mat      tmat;
320616f15bc4SStefano Zampini       PetscInt bs;
320716f15bc4SStefano Zampini 
3208906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3209906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3210bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3211bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3212bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3213bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
321416f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
321516f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3216906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3217bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3218bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3219bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3220bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3221bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3222e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3223e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3224bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3225bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3226906d46d4SStefano Zampini     }
3227906d46d4SStefano Zampini     /* check */
3228906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
3229906d46d4SStefano Zampini       PetscReal error;
3230906d46d4SStefano Zampini       Vec       x,x_change;
3231906d46d4SStefano Zampini 
3232906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3233906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3234906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3235906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3236e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3237e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3238bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
3239e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3240e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3241906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
3242906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3243906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3244906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3245bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
3246906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
3247906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3248906d46d4SStefano Zampini     }
3249b96c3477SStefano Zampini 
3250b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
3251b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
3252b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
3253b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
3254ac632422SStefano Zampini         Mat                    S_new,tmat;
3255b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
3256b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
3257b087196eSStefano Zampini         const PetscScalar      *array;
3258b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
3259b087196eSStefano Zampini         PetscInt               i,n_V;
3260bbb9e6c6SStefano Zampini 
3261bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
32626816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
3263b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
3264b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
3265b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
3266b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
3267bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
3268b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
3269ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3270b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
3271ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3272b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3273b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
3274b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3275b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3276b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
3277b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
3278b087196eSStefano Zampini           PetscScalar val;
3279b087196eSStefano Zampini           PetscInt    idx;
3280b087196eSStefano Zampini 
3281b087196eSStefano Zampini           idx = idxs_V[i];
3282b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
3283b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
3284b087196eSStefano Zampini         }
3285b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3286b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3287ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
3288ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3289ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
3290ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3291b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
3292ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3293b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3294ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
3295ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3296ac632422SStefano Zampini         }
3297b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
3298b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3299b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3300b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3301b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
3302b96c3477SStefano Zampini       }
3303b96c3477SStefano Zampini     }
3304906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
3305906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
3306b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3307b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
3308b9b85e73SStefano Zampini   }
3309906d46d4SStefano Zampini 
3310906d46d4SStefano Zampini   /* set up change of basis context */
3311906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
3312906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
3313906d46d4SStefano Zampini 
3314906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
3315906d46d4SStefano Zampini       PetscInt global_size,local_size;
3316906d46d4SStefano Zampini 
3317906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3318906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3319906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
3320906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3321906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
3322906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
3323906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3324906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3325906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3326906d46d4SStefano Zampini     } else {
3327906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3328906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3329906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3330906d46d4SStefano Zampini     }
3331906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
3332906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3333906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3334906d46d4SStefano Zampini     } else {
3335906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3336906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3337906d46d4SStefano Zampini     }
3338906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3339906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3340906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3341906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3342b9b85e73SStefano Zampini   }
3343a717540cSStefano Zampini 
3344019a44ceSStefano Zampini   /* add pressure dof to set of primal nodes for numbering purposes */
3345c9ed8603SStefano Zampini   if (pcbddc->benign_p0_lidx >= 0) {
3346c9ed8603SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx;
3347d16cbb6bSStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx;
3348019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
3349019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
3350019a44ceSStefano Zampini     pcbddc->local_primal_size++;
3351019a44ceSStefano Zampini   }
3352019a44ceSStefano Zampini 
3353019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
3354727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
3355727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
3356aff50787SStefano 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);
3357c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
33580e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
3359aff50787SStefano 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);
3360727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3361727cdba6SStefano Zampini     }
33620e6343abSStefano Zampini   }
33630e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3364727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3365727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3366727cdba6SStefano Zampini 
3367a717540cSStefano Zampini   /* flush dbg viewer */
3368b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
3369b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3370b8ffe317SStefano Zampini   }
3371a717540cSStefano Zampini 
3372e310c8b4SStefano Zampini   /* free workspace */
3373a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
33744641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
337508122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
33769162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
33779162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
337808122e43SStefano Zampini   } else {
33799162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
33809162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
33819162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
338208122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
338308122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
33849162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
33859162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
338608122e43SStefano Zampini   }
3387674ae819SStefano Zampini   PetscFunctionReturn(0);
3388674ae819SStefano Zampini }
3389674ae819SStefano Zampini 
3390674ae819SStefano Zampini #undef __FUNCT__
3391674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
3392674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3393674ae819SStefano Zampini {
3394674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3395674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
3396674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
33977fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
3398674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
3399674ae819SStefano Zampini 
3400674ae819SStefano Zampini   PetscFunctionBegin;
34018e61c736SStefano Zampini   /* Reset previously computed graph */
34028e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3403674ae819SStefano Zampini   /* Init local Graph struct */
34047fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
34053bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3406674ae819SStefano Zampini 
3407575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
3408575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
3409575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
3410575ad6abSStefano Zampini   }
34119577ea80SStefano Zampini 
3412674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
34134d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
34144d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
34154d379d7bSStefano Zampini     PetscInt  nvtxs;
3416e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
3417674ae819SStefano Zampini 
34184d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
34192fffb893SStefano Zampini 
34202fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
34212fffb893SStefano Zampini       if (flg_row) {
34224d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3423b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
34242fffb893SStefano Zampini       }
34252fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
34269b28b941SStefano 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 */
34274d379d7bSStefano Zampini       IS                     is_dummy;
34284d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
34294d379d7bSStefano Zampini       PetscInt               j,sum;
34304d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
34314d379d7bSStefano Zampini       const PetscInt         *idxs;
34324d379d7bSStefano Zampini       PCBDDCGraph            graph;
34334d379d7bSStefano Zampini       PetscBT                is_on_boundary;
34344d379d7bSStefano Zampini 
34354d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
34364d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
34374d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
34384d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
34397fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
34404d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3441e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3442e496cd5dSStefano Zampini       if (flg_row) {
34434d379d7bSStefano Zampini         graph->xadj = xadj;
34444d379d7bSStefano Zampini         graph->adjncy = adjncy;
3445e496cd5dSStefano Zampini       }
34464d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
34474d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3448e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
34494d379d7bSStefano Zampini 
34504d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
34519b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
34524d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
34534d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
34544d379d7bSStefano Zampini         }
34554d379d7bSStefano Zampini       }
34564d379d7bSStefano Zampini 
3457e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
34584d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
34594d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
34604d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
34614d379d7bSStefano Zampini       }
34624d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
34634d379d7bSStefano Zampini 
3464e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
34654d379d7bSStefano Zampini       sum = 0;
34664d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
34674d379d7bSStefano Zampini         PetscInt sizecc = 0;
34684d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
34694d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
34704d379d7bSStefano Zampini             sizecc++;
34714d379d7bSStefano Zampini           }
34724d379d7bSStefano Zampini         }
34734d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
34744d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
34754d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
34764d379d7bSStefano Zampini           }
34774d379d7bSStefano Zampini         }
34784d379d7bSStefano Zampini         sum += sizecc*sizecc;
34794d379d7bSStefano Zampini       }
34804d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
34814d379d7bSStefano Zampini       sum = 0;
3482e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
34834d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
34844d379d7bSStefano Zampini         cxadj[i] = sum;
34854d379d7bSStefano Zampini         sum += temp;
34864d379d7bSStefano Zampini       }
3487e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
34884d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
34894d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
34904d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
34914d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
34924d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
34934d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
34944d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
34954d379d7bSStefano Zampini                 sizecc++;
34964d379d7bSStefano Zampini               }
34974d379d7bSStefano Zampini             }
34984d379d7bSStefano Zampini           }
34994d379d7bSStefano Zampini         }
35004d379d7bSStefano Zampini       }
35019b28b941SStefano Zampini       if (sum) {
3502e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
35034d379d7bSStefano Zampini       } else {
35044d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
35054d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
35064d379d7bSStefano Zampini       }
35074d379d7bSStefano Zampini       graph->xadj = 0;
35084d379d7bSStefano Zampini       graph->adjncy = 0;
35094d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
35104d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
35114d379d7bSStefano Zampini     }
3512674ae819SStefano Zampini   }
35139b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
35149b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3515674ae819SStefano Zampini   }
3516674ae819SStefano Zampini 
351763602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3518674ae819SStefano Zampini   vertex_size = 1;
351963602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
352063602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
352195ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
352263602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3523e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
352463602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3525674ae819SStefano Zampini       }
352663602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
352763602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
352863602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3529674ae819SStefano Zampini     }
353063602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3531674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
353263602bcaSStefano Zampini   } else {
353363602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
353463602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3535854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
353663602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
353763602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
353863602bcaSStefano Zampini       }
353963602bcaSStefano Zampini     }
3540674ae819SStefano Zampini   }
3541674ae819SStefano Zampini 
3542674ae819SStefano Zampini   /* Setup of Graph */
3543785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3544e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3545785d1243SStefano Zampini   }
3546785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3547e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3548785d1243SStefano Zampini   }
3549302440fdSBarry Smith   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);CHKERRQ(ierr);
3550674ae819SStefano Zampini 
3551674ae819SStefano Zampini   /* Graph's connected components analysis */
3552674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3553674ae819SStefano Zampini 
3554674ae819SStefano Zampini   /* print some info to stdout */
3555674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3556302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3557674ae819SStefano Zampini   }
3558fb180af4SStefano Zampini 
3559fb180af4SStefano Zampini   /* mark topography has done */
3560fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3561674ae819SStefano Zampini   PetscFunctionReturn(0);
3562674ae819SStefano Zampini }
3563674ae819SStefano Zampini 
3564dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3565674ae819SStefano Zampini #undef __FUNCT__
3566674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3567dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3568674ae819SStefano Zampini {
3569dc456d91SStefano Zampini   PetscSF        sf;
3570dc456d91SStefano Zampini   PetscLayout    map;
3571dc456d91SStefano Zampini   const PetscInt *idxs;
3572dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
3573dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
3574dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
3575dc456d91SStefano Zampini   PetscMPIInt    commsize;
3576674ae819SStefano Zampini   PetscBool      first_found;
3577674ae819SStefano Zampini   PetscErrorCode ierr;
3578674ae819SStefano Zampini 
3579674ae819SStefano Zampini   PetscFunctionBegin;
3580dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
3581dc456d91SStefano Zampini   if (subset_mult) {
3582dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
3583dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
3584dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
3585674ae819SStefano Zampini   }
3586dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
3587dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
3588dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
3589dc456d91SStefano Zampini   for (i=0;i<n;i++) {
3590dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
3591dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
3592674ae819SStefano Zampini   }
3593dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
3594dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3595dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
3596dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
3597dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
3598dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
3599dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
3600dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
3601dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
3602dc456d91SStefano Zampini 
3603dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
3604dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
3605dc456d91SStefano Zampini   if (subset_mult) {
3606dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3607dc456d91SStefano Zampini 
3608dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3609dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
3610dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3611674ae819SStefano Zampini   } else {
3612dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
3613674ae819SStefano Zampini   }
3614dc456d91SStefano Zampini   /* local size of new subset */
3615dc456d91SStefano Zampini   n_n = 0;
3616dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
3617dc456d91SStefano Zampini 
3618dc456d91SStefano Zampini   /* global indexes in layout */
3619dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
3620dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
3621dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
3622dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
3623dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
3624dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
3625dc456d91SStefano Zampini 
3626dc456d91SStefano Zampini   /* reduce from leaves to roots */
3627dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
362864a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
362964a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
3630dc456d91SStefano Zampini 
3631dc456d91SStefano Zampini   /* count indexes in local part of layout */
3632674ae819SStefano Zampini   nlocals = 0;
3633674ae819SStefano Zampini   first_index = -1;
3634674ae819SStefano Zampini   first_found = PETSC_FALSE;
3635dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
3636dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
3637674ae819SStefano Zampini       first_found = PETSC_TRUE;
3638674ae819SStefano Zampini       first_index = i;
3639674ae819SStefano Zampini     }
3640dc456d91SStefano Zampini     nlocals += root_data[i];
3641674ae819SStefano Zampini   }
3642dc456d91SStefano Zampini 
3643dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
36445fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
3645dc456d91SStefano Zampini   start = 0;
364664a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
36475fa240b1SStefano Zampini #else
364864a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
36495fa240b1SStefano Zampini   start = start-nlocals;
36505fa240b1SStefano Zampini #endif
36515fa240b1SStefano Zampini 
3652dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
3653dc456d91SStefano Zampini     *N_n = start + nlocals;
3654dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
3655dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3656674ae819SStefano Zampini   }
36575fa240b1SStefano Zampini 
36585fa240b1SStefano Zampini   /* adapt root data with cumulative */
3659674ae819SStefano Zampini   if (first_found) {
3660dc456d91SStefano Zampini     PetscInt old_index;
3661dc456d91SStefano Zampini 
3662dc456d91SStefano Zampini     root_data[first_index] += start;
3663674ae819SStefano Zampini     old_index = first_index;
3664dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
3665dc456d91SStefano Zampini       if (root_data[i]) {
3666dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
3667674ae819SStefano Zampini         old_index = i;
3668674ae819SStefano Zampini       }
3669674ae819SStefano Zampini     }
3670674ae819SStefano Zampini   }
3671dc456d91SStefano Zampini 
3672dc456d91SStefano Zampini   /* from roots to leaves */
3673dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3674dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
3675dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
3676dc456d91SStefano Zampini 
3677dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
3678dc456d91SStefano Zampini   if (subset_mult) {
3679dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3680dc456d91SStefano Zampini     PetscInt        cum;
3681dc456d91SStefano Zampini 
3682dc456d91SStefano Zampini     cum = 0;
3683dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3684dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3685dc456d91SStefano Zampini       PetscInt j;
3686dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
3687674ae819SStefano Zampini     }
3688dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3689674ae819SStefano Zampini   } else {
3690dc456d91SStefano Zampini     for (i=0;i<n;i++) {
3691dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
3692674ae819SStefano Zampini     }
3693674ae819SStefano Zampini   }
3694dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
3695dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
3696674ae819SStefano Zampini   PetscFunctionReturn(0);
3697674ae819SStefano Zampini }
36989a7d3425SStefano Zampini 
36999a7d3425SStefano Zampini #undef __FUNCT__
37009a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
37019a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
37029a7d3425SStefano Zampini {
37039a7d3425SStefano Zampini   PetscInt       i,j;
37049a7d3425SStefano Zampini   PetscScalar    *alphas;
37059a7d3425SStefano Zampini   PetscErrorCode ierr;
37069a7d3425SStefano Zampini 
37079a7d3425SStefano Zampini   PetscFunctionBegin;
37089a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
3709785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
37109a7d3425SStefano Zampini   for (i=0;i<n;i++) {
37119a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
37129a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
37139a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
37149a7d3425SStefano Zampini   }
37159a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
37169a7d3425SStefano Zampini   PetscFunctionReturn(0);
37179a7d3425SStefano Zampini }
37189a7d3425SStefano Zampini 
3719e7931f94SStefano Zampini #undef __FUNCT__
372070cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
3721b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
3722e7931f94SStefano Zampini {
372352e5ac9dSStefano Zampini   IS             ranks_send_to;
3724e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
3725e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
372652e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
372752e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
37283837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
37292b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
3730e7931f94SStefano Zampini   PetscSubcomm   subcomm;
373152e5ac9dSStefano Zampini   PetscErrorCode ierr;
3732a57a6d2fSStefano Zampini 
3733e7931f94SStefano Zampini   PetscFunctionBegin;
37342b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
37352b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
37362b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
3737e7931f94SStefano Zampini 
3738e7931f94SStefano Zampini   /* Get info on mapping */
37393bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
37403bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3741e7931f94SStefano Zampini 
3742e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
3743785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
3744e7931f94SStefano Zampini   xadj[0] = 0;
3745e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
3746785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
3747785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
3748e7931f94SStefano Zampini 
37492b510759SStefano Zampini   if (threshold) {
3750d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
37512b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3752d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3753d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3754d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3755d023bfaeSStefano Zampini         xadj_count++;
3756e7931f94SStefano Zampini       }
3757e7931f94SStefano Zampini     }
3758d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3759c8587f34SStefano Zampini   } else {
3760e7931f94SStefano Zampini     if (xadj[1]) {
3761e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3762e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3763c8587f34SStefano Zampini     }
3764e7931f94SStefano Zampini   }
37653bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3766e7931f94SStefano Zampini   if (use_square) {
3767e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3768e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3769e7931f94SStefano Zampini     }
3770e7931f94SStefano Zampini   }
3771e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3772e7931f94SStefano Zampini 
37733837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3774e7931f94SStefano Zampini 
3775e7931f94SStefano Zampini   /*
3776e7931f94SStefano Zampini     Restrict work on active processes only.
3777e7931f94SStefano Zampini   */
3778e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3779e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3780e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
37812b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3782d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3783e7931f94SStefano Zampini   if (color) {
3784e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3785e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3786e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3787c8587f34SStefano Zampini   } else {
378852e5ac9dSStefano Zampini     Mat             subdomain_adj;
378952e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
379052e5ac9dSStefano Zampini     MatPartitioning partitioner;
379152e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
379252e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
3793b0c7d250SStefano Zampini     PetscBool       aggregate;
3794b0c7d250SStefano Zampini 
3795306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
3796785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3797e7931f94SStefano Zampini     prank = rank;
3798306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
37998002ef2cSStefano Zampini     /*
3800e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3801e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3802c8587f34SStefano Zampini     }
38038002ef2cSStefano Zampini     */
3804e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3805e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3806c8587f34SStefano Zampini     }
3807e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3808b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
3809b0c7d250SStefano Zampini     if (aggregate) {
3810b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
3811b0c7d250SStefano Zampini       PetscMPIInt nrank;
3812b0c7d250SStefano Zampini       PetscScalar *vals;
3813b0c7d250SStefano Zampini 
3814b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
3815b0c7d250SStefano Zampini       lrows = 0;
3816b0c7d250SStefano Zampini       if (nrank<redprocs) {
3817b0c7d250SStefano Zampini         lrows = size/redprocs;
3818b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
3819b0c7d250SStefano Zampini       }
38205fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
3821b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
3822b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3823b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
3824b0c7d250SStefano Zampini       row = nrank;
3825b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
3826b0c7d250SStefano Zampini       cols = adjncy;
3827b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
3828b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
3829b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
3830b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3831b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
383252e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
383352e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
383452e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3835b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
3836b0c7d250SStefano Zampini     } else {
3837306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
3838b0c7d250SStefano Zampini     }
383922b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3840e7931f94SStefano Zampini 
3841e7931f94SStefano Zampini     /* Partition */
3842306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
3843e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3844e7931f94SStefano Zampini     if (use_vwgt) {
38453837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3846e7931f94SStefano Zampini       v_wgt[0] = local_size;
3847e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3848c8587f34SStefano Zampini     }
384928143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
385028143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3851e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3852e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
385322b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3854e7931f94SStefano Zampini 
385552e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
385652e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
385752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
385852e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3859b0c7d250SStefano Zampini     if (!redprocs) {
3860b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
386128143c3dSStefano Zampini     } else {
3862b0c7d250SStefano Zampini       PetscInt    idxs[1];
3863b0c7d250SStefano Zampini       PetscMPIInt tag;
3864b0c7d250SStefano Zampini       MPI_Request *reqs;
3865b0c7d250SStefano Zampini 
3866b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
3867b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
3868b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
3869b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
387028143c3dSStefano Zampini       }
3871b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
3872b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3873b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
3874b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
3875e7931f94SStefano Zampini     }
387652e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3877e7931f94SStefano Zampini     /* clean up */
3878e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
387952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
3880e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3881e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3882e7931f94SStefano Zampini   }
3883e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3884e7931f94SStefano Zampini 
3885e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3886e7931f94SStefano Zampini   i = 1;
3887e7931f94SStefano Zampini   if (color) i=0;
3888e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3889e7931f94SStefano Zampini   /* get back IS */
3890e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3891e7931f94SStefano Zampini   PetscFunctionReturn(0);
3892e7931f94SStefano Zampini }
3893e7931f94SStefano Zampini 
3894e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3895e7931f94SStefano Zampini 
3896e7931f94SStefano Zampini #undef __FUNCT__
3897e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
389853a05cb3SStefano 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[])
3899e7931f94SStefano Zampini {
390070cf5478SStefano Zampini   Mat                    local_mat;
3901e7931f94SStefano Zampini   IS                     is_sends_internal;
39029d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
390328143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
39049d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3905e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3906e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3907e7931f94SStefano Zampini   const PetscInt*        is_indices;
3908e7931f94SStefano Zampini   MatType                new_local_type;
3909e7931f94SStefano Zampini   /* buffers */
3910e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
391128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
39129d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3913e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3914e7931f94SStefano Zampini   /* MPI */
391528143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
391628143c3dSStefano Zampini   PetscSubcomm           subcomm;
3917e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
391828143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
391928143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
392028143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
392128143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
392228143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3923e7931f94SStefano Zampini   PetscErrorCode         ierr;
3924e7931f94SStefano Zampini 
3925e7931f94SStefano Zampini   PetscFunctionBegin;
392628143c3dSStefano Zampini   /* TODO: add missing checks */
392728143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
392828143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
392928143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
393028143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3931e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
393228143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3933e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3934e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3935e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3936e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3937e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
393828143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
393970cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
394070cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
394128143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
394270cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
394370cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
394470cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
394570cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
394670cf5478SStefano Zampini   }
3947e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3948e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3949e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3950e7931f94SStefano Zampini   if (!is_sends) {
395128143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
3952b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
3953c8587f34SStefano Zampini   } else {
3954e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3955e7931f94SStefano Zampini     is_sends_internal = is_sends;
3956c8587f34SStefano Zampini   }
3957e7931f94SStefano Zampini 
3958e7931f94SStefano Zampini   /* get comm */
3959a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3960e7931f94SStefano Zampini 
3961e7931f94SStefano Zampini   /* compute number of sends */
3962e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3963e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3964e7931f94SStefano Zampini 
3965e7931f94SStefano Zampini   /* compute number of receives */
3966e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3967785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3968e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3969e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3970e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3971e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3972e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3973e7931f94SStefano Zampini 
397428143c3dSStefano Zampini   /* restrict comm if requested */
397528143c3dSStefano Zampini   subcomm = 0;
397628143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
397728143c3dSStefano Zampini   if (restrict_comm) {
3978779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
3979779c1cceSStefano Zampini 
398028143c3dSStefano Zampini     color = 0;
398153a05cb3SStefano Zampini     if (restrict_full) {
398253a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
398353a05cb3SStefano Zampini     } else {
398453a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
398553a05cb3SStefano Zampini     }
398628143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
398728143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
398828143c3dSStefano Zampini     /* check if reuse has been requested */
398928143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
399028143c3dSStefano Zampini       if (*mat_n) {
399128143c3dSStefano Zampini         PetscMPIInt subcommsize2;
399228143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
399328143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
399428143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
399528143c3dSStefano Zampini       } else {
399628143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
399728143c3dSStefano Zampini       }
399828143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
3999779c1cceSStefano Zampini       PetscMPIInt rank;
4000779c1cceSStefano Zampini 
4001779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
400228143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
400328143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
400428143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4005306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
400628143c3dSStefano Zampini     }
400728143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
400828143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
400928143c3dSStefano Zampini   } else {
401028143c3dSStefano Zampini     comm_n = comm;
401128143c3dSStefano Zampini   }
401228143c3dSStefano Zampini 
4013e7931f94SStefano Zampini   /* prepare send/receive buffers */
4014785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4015e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4016785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4017e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
401828143c3dSStefano Zampini   if (nis) {
4019854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
402028143c3dSStefano Zampini   }
4021e7931f94SStefano Zampini 
402228143c3dSStefano Zampini   /* Get data from local matrices */
4023e7931f94SStefano Zampini   if (!isdense) {
4024a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4025e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4026e7931f94SStefano Zampini     /*
4027e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4028e7931f94SStefano Zampini        send_buffer_idxs should contain:
4029e7931f94SStefano Zampini        - MatType_PRIVATE type
4030e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4031e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4032e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4033e7931f94SStefano Zampini     */
4034e7931f94SStefano Zampini   } else {
4035e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
40363bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4037854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4038e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4039e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
40403bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4041e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
40423bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4043e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4044e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4045e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4046e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4047c8587f34SStefano Zampini     }
4048c8587f34SStefano Zampini   }
4049e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
405028143c3dSStefano Zampini   /* additional is (if any) */
405128143c3dSStefano Zampini   if (nis) {
405228143c3dSStefano Zampini     PetscMPIInt psum;
405328143c3dSStefano Zampini     PetscInt j;
405428143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
405528143c3dSStefano Zampini       PetscInt plen;
405628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
405728143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
405828143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
405928143c3dSStefano Zampini     }
4060854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
406128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
406228143c3dSStefano Zampini       PetscInt plen;
406328143c3dSStefano Zampini       const PetscInt *is_array_idxs;
406428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
406528143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
406628143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
406728143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
406828143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
406928143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
407028143c3dSStefano Zampini     }
407128143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
407228143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
407328143c3dSStefano Zampini     }
407428143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
407528143c3dSStefano Zampini   }
407628143c3dSStefano Zampini 
4077e7931f94SStefano Zampini   buf_size_idxs = 0;
4078e7931f94SStefano Zampini   buf_size_vals = 0;
407928143c3dSStefano Zampini   buf_size_idxs_is = 0;
4080e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4081e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4082e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
408328143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4084e7931f94SStefano Zampini   }
4085785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4086785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
408795ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4088e7931f94SStefano Zampini 
4089e7931f94SStefano Zampini   /* get new tags for clean communications */
4090e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4091e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
409228143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4093e7931f94SStefano Zampini 
4094e7931f94SStefano Zampini   /* allocate for requests */
4095785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4096785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
409795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4098785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4099785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
410095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4101e7931f94SStefano Zampini 
4102e7931f94SStefano Zampini   /* communications */
4103e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4104e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
410528143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4106e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4107e7931f94SStefano Zampini     source_dest = onodes[i];
4108e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4109e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4110e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4111e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
411228143c3dSStefano Zampini     if (nis) {
411328143c3dSStefano 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);
411428143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
411528143c3dSStefano Zampini     }
4116e7931f94SStefano Zampini   }
4117e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4118e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4119e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4120e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
412128143c3dSStefano Zampini     if (nis) {
412228143c3dSStefano 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);
412328143c3dSStefano Zampini     }
4124e7931f94SStefano Zampini   }
4125e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4126e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4127e7931f94SStefano Zampini 
4128e7931f94SStefano Zampini   /* assemble new l2g map */
4129e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4130e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
41319d30be91SStefano Zampini   new_local_rows = 0;
4132e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
41339d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4134e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4135e7931f94SStefano Zampini   }
41369d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4137e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
41389d30be91SStefano Zampini   new_local_rows = 0;
4139e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
41409d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
41419d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4142e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4143e7931f94SStefano Zampini   }
41449d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
41459d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4146e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4147e7931f94SStefano Zampini 
4148e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4149e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4150e7931f94SStefano 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) */
4151e7931f94SStefano Zampini   if (n_recvs) {
415228143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4153e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4154e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4155e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4156e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4157e7931f94SStefano Zampini         break;
4158e7931f94SStefano Zampini       }
4159e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4160e7931f94SStefano Zampini     }
4161e7931f94SStefano Zampini     switch (new_local_type_private) {
416228143c3dSStefano Zampini       case MATDENSE_PRIVATE:
416328143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4164e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4165e7931f94SStefano Zampini           bs = 1;
416628143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
416728143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
416828143c3dSStefano Zampini           bs = 1;
416928143c3dSStefano Zampini         }
4170e7931f94SStefano Zampini         break;
4171e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4172e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4173e7931f94SStefano Zampini         bs = 1;
4174e7931f94SStefano Zampini         break;
4175e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4176e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4177e7931f94SStefano Zampini         break;
4178e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4179e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4180e7931f94SStefano Zampini         break;
4181e7931f94SStefano Zampini       default:
41829d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4183e7931f94SStefano Zampini         break;
4184e7931f94SStefano Zampini     }
418528143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
418628143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
418728143c3dSStefano Zampini     bs = 1;
4188e7931f94SStefano Zampini   }
4189e7931f94SStefano Zampini 
419070cf5478SStefano Zampini   /* create MATIS object if needed */
419170cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4192e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4193e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
419470cf5478SStefano Zampini   } else {
419570cf5478SStefano Zampini     /* it also destroys the local matrices */
419670cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
419770cf5478SStefano Zampini   }
419870cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4199e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
42009d30be91SStefano Zampini 
42019d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
42029d30be91SStefano Zampini 
42039d30be91SStefano Zampini   /* Global to local map of received indices */
42049d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
42059d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
42069d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
42079d30be91SStefano Zampini 
42089d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
42099d30be91SStefano Zampini   buf_size_idxs = 0;
42109d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
42119d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
42129d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
42139d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
42149d30be91SStefano Zampini   }
42159d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
42169d30be91SStefano Zampini 
42179d30be91SStefano Zampini   /* set preallocation */
42189d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
42199d30be91SStefano Zampini   if (!newisdense) {
42209d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
42219d30be91SStefano Zampini 
42229d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
42239d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
42249d30be91SStefano Zampini     if (n_recvs) {
42259d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
42269d30be91SStefano Zampini     }
42279d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
42289d30be91SStefano Zampini       PetscInt j;
42299d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
42309d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
42319d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
42329d30be91SStefano Zampini         }
42339d30be91SStefano Zampini       } else {
42349d30be91SStefano Zampini         /* TODO */
42359d30be91SStefano Zampini       }
42369d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
42379d30be91SStefano Zampini     }
42389d30be91SStefano Zampini     if (new_local_nnz) {
42399d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
42409d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
42419d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
42429d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
42439d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
42449d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
42459d30be91SStefano Zampini     } else {
42469d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
42479d30be91SStefano Zampini     }
42489d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
42499d30be91SStefano Zampini   } else {
42509d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
42519d30be91SStefano Zampini   }
4252e7931f94SStefano Zampini 
4253e7931f94SStefano Zampini   /* set values */
4254e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
42559d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
4256e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4257e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
4258e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
42599d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
4260e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4261e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4262e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
426328143c3dSStefano Zampini     } else {
426428143c3dSStefano Zampini       /* TODO */
4265e7931f94SStefano Zampini     }
4266e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4267e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
4268e7931f94SStefano Zampini   }
4269e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4270e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
427170cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
427270cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
42739d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
42749d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
4275e7931f94SStefano Zampini 
4276dfd14d43SStefano Zampini #if 0
427728143c3dSStefano Zampini   if (!restrict_comm) { /* check */
4278e7931f94SStefano Zampini     Vec       lvec,rvec;
4279e7931f94SStefano Zampini     PetscReal infty_error;
4280e7931f94SStefano Zampini 
42812a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
4282e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
4283e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
4284e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
428570cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
4286e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4287e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
4288e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
4289e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
4290e7931f94SStefano Zampini   }
429128143c3dSStefano Zampini #endif
4292e7931f94SStefano Zampini 
429328143c3dSStefano Zampini   /* assemble new additional is (if any) */
429428143c3dSStefano Zampini   if (nis) {
429528143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
429628143c3dSStefano Zampini 
429728143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4298854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
429928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
430028143c3dSStefano Zampini     psum = 0;
430128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
430228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
430328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
430428143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
430528143c3dSStefano Zampini         psum += plen;
430628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
430728143c3dSStefano Zampini       }
430828143c3dSStefano Zampini     }
4309854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
4310854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
431128143c3dSStefano Zampini     for (i=1;i<nis;i++) {
431228143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
431328143c3dSStefano Zampini     }
431428143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
431528143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
431628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
431728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
431828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
431928143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
432028143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
432128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
432228143c3dSStefano Zampini       }
432328143c3dSStefano Zampini     }
432428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
432528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
432628143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
432728143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
432828143c3dSStefano Zampini     }
432928143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
433028143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
433128143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
433228143c3dSStefano Zampini   }
4333e7931f94SStefano Zampini   /* free workspace */
433428143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4335e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4336e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4337e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4338e7931f94SStefano Zampini   if (isdense) {
4339e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4340e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4341e7931f94SStefano Zampini   } else {
4342e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4343e7931f94SStefano Zampini   }
434428143c3dSStefano Zampini   if (nis) {
434528143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
434628143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
434728143c3dSStefano Zampini   }
4348e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4349e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
435028143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4351e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4352e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
435328143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4354e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4355e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4356e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4357e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4358e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
435928143c3dSStefano Zampini   if (nis) {
436028143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
436128143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
436228143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
436328143c3dSStefano Zampini   }
436428143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
436528143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
436628143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
436728143c3dSStefano Zampini     for (i=0;i<nis;i++) {
436828143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
436928143c3dSStefano Zampini     }
437053a05cb3SStefano Zampini     *mat_n = NULL;
437128143c3dSStefano Zampini   }
4372e7931f94SStefano Zampini   PetscFunctionReturn(0);
4373e7931f94SStefano Zampini }
4374a57a6d2fSStefano Zampini 
437512edc857SStefano Zampini /* temporary hack into ksp private data structure */
4376af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
437712edc857SStefano Zampini 
4378c8587f34SStefano Zampini #undef __FUNCT__
4379c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4380c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4381c8587f34SStefano Zampini {
4382c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4383c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
438420a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
43859881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
438620a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
43876e683305SStefano Zampini   IS                     coarse_is,*isarray;
43886e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
43896e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
4390f9eb5b7dSStefano Zampini   PC                     pc_temp;
4391c8587f34SStefano Zampini   PCType                 coarse_pc_type;
4392c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
4393f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
43944f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
43956e683305SStefano Zampini   Mat                    t_coarse_mat_is;
43966e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
43976e683305SStefano Zampini   PetscMPIInt            all_procs;
439874e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
439968457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
440022bc73bbSStefano Zampini   PetscScalar            *array;
44019881197aSStefano Zampini   PetscErrorCode         ierr;
4402fdc09c96SStefano Zampini 
4403c8587f34SStefano Zampini   PetscFunctionBegin;
4404c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
440568457ee5SStefano 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 */
4406fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
44075a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
4408fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
4409f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4410f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4411f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
4412fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
441351bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
441451bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4415dc4bcba2SStefano Zampini         PC        pc;
4416dc4bcba2SStefano Zampini         PetscBool isbddc;
4417dc4bcba2SStefano Zampini 
4418dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
4419dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4420dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4421dc4bcba2SStefano Zampini         if (isbddc) {
4422dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4423dc4bcba2SStefano Zampini         }
4424727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4425fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
4426fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
4427fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
4428f4ddd8eeSStefano Zampini       }
4429fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4430fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
4431f4ddd8eeSStefano Zampini     }
443270cf5478SStefano Zampini     /* reset any subassembling information */
443370cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
44346e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
44356e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4436fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
4437f4ddd8eeSStefano Zampini   }
4438c8587f34SStefano Zampini 
44396e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
44402b510759SStefano Zampini   im_active = !!(pcis->n);
44412b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
44426e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
44436e683305SStefano Zampini   void_procs = all_procs-active_procs;
44446e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
444574e2c79eSStefano Zampini   redist = PETSC_FALSE;
444622bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
44476e683305SStefano Zampini     csin_ml = PETSC_TRUE;
44486e683305SStefano Zampini     ncoarse_ml = void_procs;
4449779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4450779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
44516e683305SStefano Zampini       csin_ds = PETSC_TRUE;
445218a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
445318a45a71SStefano Zampini       redist = PETSC_TRUE;
445418a45a71SStefano Zampini     } else {
44556e683305SStefano Zampini       csin_ds = PETSC_TRUE;
4456779c1cceSStefano Zampini       ncoarse_ds = active_procs;
4457779c1cceSStefano Zampini       redist = PETSC_TRUE;
445818a45a71SStefano Zampini     }
44596e683305SStefano Zampini   } else {
44606e683305SStefano Zampini     csin_ml = PETSC_FALSE;
44616e683305SStefano Zampini     ncoarse_ml = all_procs;
44626e683305SStefano Zampini     if (void_procs) {
44636e683305SStefano Zampini       csin_ds = PETSC_TRUE;
44646e683305SStefano Zampini       ncoarse_ds = void_procs;
44656e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
44666e683305SStefano Zampini     } else {
4467779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
446874e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
446974e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
447074e2c79eSStefano Zampini         redist = PETSC_TRUE;
447174e2c79eSStefano Zampini       } else {
44726e683305SStefano Zampini         csin_ds = PETSC_FALSE;
44736e683305SStefano Zampini         ncoarse_ds = all_procs;
44746e683305SStefano Zampini       }
44756e683305SStefano Zampini     }
447674e2c79eSStefano Zampini   }
44776e683305SStefano Zampini 
44786e683305SStefano Zampini   /*
44796e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
44806e683305SStefano Zampini     - we have not exceeded the number of levels requested
44816e683305SStefano Zampini     - we can actually subassemble the active processes
44826e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
44836e683305SStefano Zampini   */
44846e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
44856e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
44866e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
44876e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
44886e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4489f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
44902b510759SStefano Zampini     } else {
4491f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
4492c8587f34SStefano Zampini     }
4493c8587f34SStefano Zampini   }
44946e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
44956e683305SStefano Zampini   if (multilevel_allowed) {
44966e683305SStefano Zampini     ncoarse = ncoarse_ml;
44976e683305SStefano Zampini     csin = csin_ml;
449858da7f69SStefano Zampini     redist = PETSC_FALSE;
44996e683305SStefano Zampini   } else {
45006e683305SStefano Zampini     ncoarse = ncoarse_ds;
45016e683305SStefano Zampini     csin = csin_ds;
45026e683305SStefano Zampini   }
4503e7931f94SStefano Zampini 
4504abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
4505abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4506abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4507abbbba34SStefano Zampini 
4508abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
450922bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
451022bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
451122bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
451222bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4513b1ecc7b1SStefano Zampini #if 0
4514b9b85e73SStefano Zampini   {
4515b9b85e73SStefano Zampini     PetscViewer viewer;
4516b9b85e73SStefano Zampini     char filename[256];
4517b1ecc7b1SStefano Zampini     sprintf(filename,"local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4518b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4519b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4520b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
4521b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4522b9b85e73SStefano Zampini   }
4523b9b85e73SStefano Zampini #endif
4524e176bc59SStefano 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);
45256e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
45266e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45276e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4528abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4529abbbba34SStefano Zampini 
45306e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
45316e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
45326e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
45336e683305SStefano Zampini     const PetscInt         *idxs;
45346e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
45356e683305SStefano Zampini 
45366e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
45370be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
45386e683305SStefano Zampini     /* allocate space for temporary storage */
4539854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4540854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
45416e683305SStefano Zampini     /* allocate for IS array */
45426e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
45436e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
45446e683305SStefano Zampini     nis = nisdofs + nisneu;
4545854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
45466e683305SStefano Zampini     /* dofs splitting */
45476e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
45486e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
45496e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
45506e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
45516e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
45526e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
45536e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
45546e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
45556e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
45566e683305SStefano Zampini     }
45576e683305SStefano Zampini     /* neumann boundaries */
45586e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
45596e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
45606e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
45616e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
45626e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
45636e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
45646e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
45656e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
45666e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
45676e683305SStefano Zampini     }
45686e683305SStefano Zampini     /* free memory */
45696e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
45706e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
45716e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
45726e683305SStefano Zampini   } else {
45736e683305SStefano Zampini     nis = 0;
45746e683305SStefano Zampini     nisdofs = 0;
45756e683305SStefano Zampini     nisneu = 0;
45766e683305SStefano Zampini     isarray = NULL;
45776e683305SStefano Zampini   }
45786e683305SStefano Zampini   /* destroy no longer needed map */
45796e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
45806e683305SStefano Zampini 
45816e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
45826e683305SStefano Zampini   coarse_mat_is = NULL;
45836e683305SStefano Zampini   if (csin) {
45846e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
458574e2c79eSStefano Zampini       if (redist) {
458674e2c79eSStefano Zampini         PetscMPIInt rank;
4587779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
458874e2c79eSStefano Zampini 
458974e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
459058da7f69SStefano Zampini         spc = active_procs/ncoarse;
459158da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
4592779c1cceSStefano Zampini         if (im_active) {
4593779c1cceSStefano Zampini           destsize = 1;
459474e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
459574e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
459674e2c79eSStefano Zampini           } else {
459774e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
459874e2c79eSStefano Zampini           }
459974e2c79eSStefano Zampini         } else {
4600779c1cceSStefano Zampini           destsize = 0;
46016e683305SStefano Zampini         }
4602779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4603779c1cceSStefano Zampini       } else if (csin_type_simple) {
46046e683305SStefano Zampini         PetscMPIInt rank;
46056e683305SStefano Zampini         PetscInt    issize,isidx;
4606779c1cceSStefano Zampini 
46076e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
46086e683305SStefano Zampini         if (im_active) {
46096e683305SStefano Zampini           issize = 1;
46106e683305SStefano Zampini           isidx = (PetscInt)rank;
46116e683305SStefano Zampini         } else {
46126e683305SStefano Zampini           issize = 0;
46136e683305SStefano Zampini           isidx = -1;
46146e683305SStefano Zampini         }
46156e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4616779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
4617b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
46186e683305SStefano Zampini       }
4619779c1cceSStefano Zampini 
4620779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
4621779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
4622779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
4623779c1cceSStefano Zampini         PetscInt *coarse_candidates;
4624779c1cceSStefano Zampini         const PetscInt* tisindices;
4625779c1cceSStefano Zampini 
4626779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
4627779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
4628779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4629779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
4630779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
4631779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
4632779c1cceSStefano Zampini           }
4633779c1cceSStefano Zampini         }
4634779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
4635779c1cceSStefano Zampini 
4636779c1cceSStefano Zampini 
46376e683305SStefano Zampini         if (pcbddc->dbg_flag) {
46386e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
46396e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
46406e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
46416e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
4642779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
46436e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
46446e683305SStefano Zampini           }
46456e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
46466e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
46476e683305SStefano Zampini         }
46486e683305SStefano Zampini         /* shift the pattern on coarse candidates */
46496e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
46506e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
4651854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
46526e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
46536e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
46546e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
46556e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
46566e683305SStefano Zampini       }
46576e683305SStefano Zampini       if (pcbddc->dbg_flag) {
46586e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
46596e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
46606e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
46616e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
46626e683305SStefano Zampini       }
4663779c1cceSStefano Zampini     }
46646e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
466553a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
466653a05cb3SStefano 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);
466753a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
466853a05cb3SStefano 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);
466953a05cb3SStefano Zampini     }
46706e683305SStefano Zampini   } else {
46716e683305SStefano Zampini     if (pcbddc->dbg_flag) {
46726e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
46736e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
46746e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
46756e683305SStefano Zampini     }
46766e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
46776e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
46786e683305SStefano Zampini   }
46796e683305SStefano Zampini 
46806e683305SStefano Zampini   /* create local to global scatters for coarse problem */
468168457ee5SStefano Zampini   if (compute_vecs) {
46826e683305SStefano Zampini     PetscInt lrows;
46836e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
46846e683305SStefano Zampini     if (coarse_mat_is) {
46856e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
46866e683305SStefano Zampini     } else {
46876e683305SStefano Zampini       lrows = 0;
46886e683305SStefano Zampini     }
46896e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
46906e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
46916e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
46926e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
46936e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
46946e683305SStefano Zampini   }
46956e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
46966e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
4697c8587f34SStefano Zampini 
4698f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
4699f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
4700f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
4701f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
4702f9eb5b7dSStefano Zampini   } else {
4703f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
4704f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
4705c8587f34SStefano Zampini   }
4706c8587f34SStefano Zampini 
47076e683305SStefano Zampini   /* print some info if requested */
47086e683305SStefano Zampini   if (pcbddc->dbg_flag) {
47096e683305SStefano Zampini     if (!multilevel_allowed) {
47106e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
47116e683305SStefano Zampini       if (multilevel_requested) {
47126e683305SStefano 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);
47136e683305SStefano Zampini       } else if (pcbddc->max_levels) {
47146e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
47156e683305SStefano Zampini       }
47166e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
47176e683305SStefano Zampini     }
47186e683305SStefano Zampini   }
47196e683305SStefano Zampini 
4720f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
47216e683305SStefano Zampini   if (coarse_mat_is) {
47226e683305SStefano Zampini     MatReuse coarse_mat_reuse;
47236a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
47246e683305SStefano Zampini     if (pcbddc->dbg_flag) {
47256e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
47266e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
47276e683305SStefano Zampini     }
4728f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
4729312be037SStefano Zampini       char prefix[256],str_level[16];
4730e604994aSStefano Zampini       size_t len;
47316e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
4732422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
4733c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
4734f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
47355f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
4736c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
47376e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
4738c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
4739c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4740e604994aSStefano Zampini       /* prefix */
4741e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
4742e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4743e604994aSStefano Zampini       if (!pcbddc->current_level) {
4744e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4745e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
4746c8587f34SStefano Zampini       } else {
4747e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4748312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4749312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
475034d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4751312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4752e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
4753e604994aSStefano Zampini       }
4754e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
47553e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
47563e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
47573e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
47583e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
4759f9eb5b7dSStefano Zampini       /* allow user customization */
4760f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
47613e3c6dadSStefano Zampini     }
47623e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
476351bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
47643e3c6dadSStefano Zampini     if (nisdofs) {
47653e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
47663e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
47673e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
47683e3c6dadSStefano Zampini       }
47693e3c6dadSStefano Zampini     }
47703e3c6dadSStefano Zampini     if (nisneu) {
47713e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
47723e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
4773312be037SStefano Zampini     }
4774f9eb5b7dSStefano Zampini 
4775f9eb5b7dSStefano Zampini     /* get some info after set from options */
4776f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
4777f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
47784f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
47796e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
4780f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
4781f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
4782f9eb5b7dSStefano Zampini     }
478339f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
47844f3a063dSStefano Zampini     if (isredundant) {
47854f3a063dSStefano Zampini       KSP inner_ksp;
47864f3a063dSStefano Zampini       PC  inner_pc;
47874f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
47884f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
47894f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
47904f3a063dSStefano Zampini     }
4791f9eb5b7dSStefano Zampini 
4792f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
4793fa7f1dd8SStefano Zampini     if (coarse_reuse) {
479481d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
4795fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
47966e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
4797fa7f1dd8SStefano Zampini     } else {
47986e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
4799fa7f1dd8SStefano Zampini     }
4800c8587f34SStefano Zampini     if (isbddc || isnn) {
480122bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
480270cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
4803b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
480422b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
48056e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
48066e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
48076e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
48086e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
480922b6e8a2SStefano Zampini           }
481070cf5478SStefano Zampini         }
481153a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
481270cf5478SStefano Zampini       } else {
481322bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
481422bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
481522bc73bbSStefano Zampini       }
481622bc73bbSStefano Zampini     } else {
48172e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
4818c8587f34SStefano Zampini     }
4819c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
4820c8587f34SStefano Zampini 
48213301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
48225a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
48233301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
48243301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
48253301b35fSStefano Zampini     }
48263301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
48273301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
48283301b35fSStefano Zampini     }
48293301b35fSStefano Zampini     if (pc->pmat->spd_set) {
48303301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
48313301b35fSStefano Zampini     }
48326e683305SStefano Zampini     /* set operators */
48335f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
48346e683305SStefano Zampini     if (pcbddc->dbg_flag) {
48356e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
48366e683305SStefano Zampini     }
48376e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
48386e683305SStefano Zampini     coarse_mat = 0;
48396e683305SStefano Zampini   }
48406e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
4841b1ecc7b1SStefano Zampini #if 0
4842b9b85e73SStefano Zampini   {
4843b9b85e73SStefano Zampini     PetscViewer viewer;
4844b9b85e73SStefano Zampini     char filename[256];
4845b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
4846b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
4847b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4848b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4849b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4850b9b85e73SStefano Zampini   }
4851b9b85e73SStefano Zampini #endif
4852c8587f34SStefano Zampini 
4853c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4854298c0119SStefano Zampini #if 0
4855c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4856c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
485798a51de6SStefano Zampini   }
4858298c0119SStefano Zampini #endif
485998a51de6SStefano Zampini 
486098a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
486198a51de6SStefano Zampini     Vec crhs,csol;
486298a51de6SStefano Zampini     PetscBool ispreonly;
486304708bb6SStefano Zampini 
486498a51de6SStefano Zampini     if (CoarseNullSpace) {
4865c8587f34SStefano Zampini       if (isbddc) {
4866c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4867c8587f34SStefano Zampini       } else {
48685fa7ec2dSBarry Smith         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
4869c8587f34SStefano Zampini       }
4870c8587f34SStefano Zampini     }
4871f9eb5b7dSStefano Zampini     /* setup coarse ksp */
4872f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4873f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4874f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
48756e683305SStefano Zampini     /* hack */
4876f347579bSStefano Zampini     if (!csol) {
48772a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4878f9eb5b7dSStefano Zampini     }
4879f347579bSStefano Zampini     if (!crhs) {
48802a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4881f347579bSStefano Zampini     }
4882cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4883cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
48846e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4885c8587f34SStefano Zampini       KSP       check_ksp;
48862b510759SStefano Zampini       KSPType   check_ksp_type;
4887c8587f34SStefano Zampini       PC        check_pc;
48886e683305SStefano Zampini       Vec       check_vec,coarse_vec;
48896a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
48902b510759SStefano Zampini       PetscInt  its;
48916e683305SStefano Zampini       PetscBool compute_eigs;
48926e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
48936e683305SStefano Zampini       PetscInt  neigs;
48948e185a42SStefano Zampini       const char *prefix;
4895c8587f34SStefano Zampini 
48962b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
48976e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
4898422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
489923ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4900f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
49012b510759SStefano Zampini       if (ispreonly) {
49022b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
49036e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
49042b510759SStefano Zampini       } else {
4905cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
49066e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4907c8587f34SStefano Zampini       }
4908c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
49096e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
49106e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
49116e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4912a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4913a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4914a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4915a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4916c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4917c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4918c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4919c8587f34SStefano Zampini       /* create random vec */
49206e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
49216e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
4922c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
4923c8587f34SStefano Zampini       if (CoarseNullSpace) {
4924c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
4925c8587f34SStefano Zampini       }
49266e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
4927c8587f34SStefano Zampini       /* solve coarse problem */
49286e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
4929c8587f34SStefano Zampini       if (CoarseNullSpace) {
49306e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
4931c8587f34SStefano Zampini       }
4932cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
49336e683305SStefano Zampini       if (compute_eigs) {
4934854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4935854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
49366e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
49376e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
49386e683305SStefano Zampini         lambda_min = eigs_r[0];
49396e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
49406e683305SStefano Zampini           if (lambda_max>lambda_min) {
4941cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4942cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4943cbcc2c2aSStefano Zampini           }
4944c8587f34SStefano Zampini         }
4945c8587f34SStefano Zampini       }
4946cbcc2c2aSStefano Zampini 
4947c8587f34SStefano Zampini       /* check coarse problem residual error */
49486e683305SStefano Zampini       if (pcbddc->dbg_flag) {
49496e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
49506e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
49516e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4952c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
49536e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
49546e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4955c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
4956779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
49576e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
49586e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
49596e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
49606e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
49616e683305SStefano Zampini         if (compute_eigs) {
49626e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4963deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4964c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
49656e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
49666e683305SStefano 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);
49676e683305SStefano Zampini           for (i=0;i<neigs;i++) {
49686e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4969c8587f34SStefano Zampini           }
49706e683305SStefano Zampini         }
49716e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
49726e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
49736e683305SStefano Zampini       }
4974c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
49756e683305SStefano Zampini       if (compute_eigs) {
49766e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
49776e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4978c8587f34SStefano Zampini       }
49796e683305SStefano Zampini     }
49806e683305SStefano Zampini   }
4981cbcc2c2aSStefano Zampini   /* print additional info */
4982cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
49836e683305SStefano Zampini     /* waits until all processes reaches this point */
49846e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4985cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4986cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4987cbcc2c2aSStefano Zampini   }
4988cbcc2c2aSStefano Zampini 
49892b510759SStefano Zampini   /* free memory */
4990c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4991fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4992c8587f34SStefano Zampini   PetscFunctionReturn(0);
4993c8587f34SStefano Zampini }
4994674ae819SStefano Zampini 
4995f34684f1SStefano Zampini #undef __FUNCT__
4996f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4997f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4998f34684f1SStefano Zampini {
4999f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5000f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5001f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5002dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5003dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
500473be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5005dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5006f34684f1SStefano Zampini   PetscErrorCode ierr;
5007f34684f1SStefano Zampini 
5008f34684f1SStefano Zampini   PetscFunctionBegin;
5009f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
50100e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
50110e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5012727cdba6SStefano Zampini   }
5013dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
50143bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5015dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5016dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5017dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5018dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5019dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5020dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
50210e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
50220e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
50230e6343abSStefano Zampini   }
5024dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5025dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5026dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5027dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5028dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5029f34684f1SStefano Zampini 
5030f34684f1SStefano Zampini   /* check numbering */
5031f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5032019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5033dc456d91SStefano Zampini     PetscInt    i;
5034b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5035f34684f1SStefano Zampini 
5036f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5037f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5038f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
50390fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
5040019a44ceSStefano Zampini     /* counter */
5041019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5042019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5043019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5044019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5045019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5046019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5047019a44ceSStefano Zampini 
5048f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5049f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5050727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5051f34684f1SStefano Zampini     }
5052f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5053f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5054f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5055e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5056e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5057e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5058e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5059f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5060019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5061f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5062019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
5063019a44ceSStefano Zampini         PetscInt owned = (PetscInt)(array[i]);
5064019a44ceSStefano Zampini         PetscInt neigh = (PetscInt)(array2[i]);
5065b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5066019a44ceSStefano 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);
5067f34684f1SStefano Zampini       }
5068f34684f1SStefano Zampini     }
5069019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5070b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5071f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5072f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5073f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5074f34684f1SStefano Zampini     }
5075f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5076f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5077e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5078e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5079f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5080f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5081b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5082ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5083ca8b9ea9SStefano Zampini 
5084ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
50853bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5086f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5087f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5088f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5089f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
50904bc2dc4bSStefano 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);
5091f34684f1SStefano Zampini       }
5092f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5093ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5094f34684f1SStefano Zampini     }
5095f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5096302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5097f34684f1SStefano Zampini   }
50988bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5099f34684f1SStefano Zampini   /* get back data */
5100f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5101f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5102674ae819SStefano Zampini   PetscFunctionReturn(0);
5103674ae819SStefano Zampini }
5104674ae819SStefano Zampini 
5105e456f2a8SStefano Zampini #undef __FUNCT__
5106e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5107a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5108e456f2a8SStefano Zampini {
5109e456f2a8SStefano Zampini   IS             localis_t;
5110a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5111e456f2a8SStefano Zampini   PetscScalar    *vals;
5112e456f2a8SStefano Zampini   PetscErrorCode ierr;
5113e456f2a8SStefano Zampini 
5114e456f2a8SStefano Zampini   PetscFunctionBegin;
5115a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5116e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5117854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5118e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5119e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5120a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5121a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
51221035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5123a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
51241035eff8SStefano Zampini   }
5125a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5126e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5127e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5128a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5129a7dc3881SStefano Zampini   /* now compute set in local ordering */
5130a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5131a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5132a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5133a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5134a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5135ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5136e456f2a8SStefano Zampini       lsize++;
5137e456f2a8SStefano Zampini     }
5138e456f2a8SStefano Zampini   }
5139854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5140a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5141ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5142e456f2a8SStefano Zampini       idxs[lsize++] = i;
5143e456f2a8SStefano Zampini     }
5144e456f2a8SStefano Zampini   }
5145a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5146a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5147e456f2a8SStefano Zampini   *localis = localis_t;
5148e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5149e456f2a8SStefano Zampini }
5150906d46d4SStefano Zampini 
5151906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5152906d46d4SStefano Zampini #undef __FUNCT__
5153906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5154906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5155906d46d4SStefano Zampini {
5156906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5157906d46d4SStefano Zampini   PetscErrorCode   ierr;
5158906d46d4SStefano Zampini 
5159906d46d4SStefano Zampini   PetscFunctionBegin;
5160906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5161906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5162906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5163906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5164906d46d4SStefano Zampini   PetscFunctionReturn(0);
5165906d46d4SStefano Zampini }
5166906d46d4SStefano Zampini 
5167906d46d4SStefano Zampini #undef __FUNCT__
5168906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5169906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5170906d46d4SStefano Zampini {
5171906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5172906d46d4SStefano Zampini   PetscErrorCode   ierr;
5173906d46d4SStefano Zampini 
5174906d46d4SStefano Zampini   PetscFunctionBegin;
5175906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5176906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5177906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5178906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5179906d46d4SStefano Zampini   PetscFunctionReturn(0);
5180906d46d4SStefano Zampini }
5181b96c3477SStefano Zampini 
5182b96c3477SStefano Zampini #undef __FUNCT__
5183b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
518408122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5185b96c3477SStefano Zampini {
5186a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5187b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5188b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5189a64f4aa4SStefano Zampini   Mat                 S_j;
5190b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
5191b96c3477SStefano Zampini   PetscBool           free_used_adj;
5192b96c3477SStefano Zampini   PetscErrorCode      ierr;
5193b96c3477SStefano Zampini 
5194b96c3477SStefano Zampini   PetscFunctionBegin;
5195b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
5196b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
519708122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
5198b96c3477SStefano Zampini     used_xadj = NULL;
5199b96c3477SStefano Zampini     used_adjncy = NULL;
5200b96c3477SStefano Zampini   } else {
520108122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
520208122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
520308122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
520408122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
5205b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
5206b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
5207b96c3477SStefano Zampini     } else {
52082fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
5209b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
5210b96c3477SStefano Zampini       PetscInt       nvtxs;
5211b96c3477SStefano Zampini 
52122fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
52132fffb893SStefano Zampini       if (flg_row) {
5214b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
5215b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
5216b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
5217b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
52182fffb893SStefano Zampini       } else {
52192fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
52202fffb893SStefano Zampini         used_xadj = NULL;
52212fffb893SStefano Zampini         used_adjncy = NULL;
52222fffb893SStefano Zampini       }
52232fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5224b96c3477SStefano Zampini     }
5225b96c3477SStefano Zampini   }
5226d5574798SStefano Zampini 
5227d5574798SStefano Zampini   /* setup sub_schurs data */
5228a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5229a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
5230a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
5231a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
523206a4e24aSStefano 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);
5233a64f4aa4SStefano Zampini   } else {
52346816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
523504708bb6SStefano Zampini     PetscBool isseqaij;
52365feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
52375feab87aSStefano Zampini       PetscInt n_vertices;
52385feab87aSStefano Zampini 
52395feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
52402034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
52415feab87aSStefano Zampini     }
524204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
524304708bb6SStefano Zampini     if (!isseqaij) {
524404708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
524504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
524604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
524704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
524804708bb6SStefano Zampini       } else {
524904708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
525004708bb6SStefano Zampini       }
525104708bb6SStefano Zampini     }
525206a4e24aSStefano 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);
5253a64f4aa4SStefano Zampini   }
5254a64f4aa4SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5255b96c3477SStefano Zampini 
5256b96c3477SStefano Zampini   /* free adjacency */
5257b96c3477SStefano Zampini   if (free_used_adj) {
5258b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
5259b96c3477SStefano Zampini   }
5260b96c3477SStefano Zampini   PetscFunctionReturn(0);
5261b96c3477SStefano Zampini }
5262b96c3477SStefano Zampini 
5263b96c3477SStefano Zampini #undef __FUNCT__
5264b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
526508122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
5266b96c3477SStefano Zampini {
5267b96c3477SStefano 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;
5270b96c3477SStefano Zampini   PCBDDCGraph         graph;
5271b96c3477SStefano Zampini   PetscErrorCode      ierr;
5272b96c3477SStefano Zampini 
5273b96c3477SStefano Zampini   PetscFunctionBegin;
5274b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
527508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
52763301b35fSStefano Zampini     IS       verticesIS,verticescomm;
52773301b35fSStefano Zampini     PetscInt vsize,*idxs;
5278b96c3477SStefano Zampini 
5279b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
52803301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
52813301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
52823301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
52833301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
52843301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
5285b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
52867fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
52873301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
52883301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
5289b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5290b96c3477SStefano Zampini /*
5291b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
5292b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5293b96c3477SStefano Zampini     }
5294b96c3477SStefano Zampini */
5295b96c3477SStefano Zampini   } else {
5296b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
5297b96c3477SStefano Zampini   }
5298b96c3477SStefano Zampini 
5299b96c3477SStefano Zampini   /* sub_schurs init */
5300a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
5301a64f4aa4SStefano Zampini 
5302b96c3477SStefano Zampini   /* free graph struct */
530308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
5304b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
5305b96c3477SStefano Zampini   }
5306b96c3477SStefano Zampini   PetscFunctionReturn(0);
5307b96c3477SStefano Zampini }
5308